1
\$\begingroup\$

I'm creating a simple MVC framework for a new version of my website I'm working on. Currently I have simple routing, such as /about-us etc ...

I've just implemented 'my version' of dynamic routing. I have no idea whether or not my implementation is idiotic or not. I made it up as I went along, so I've no idea if this is a horrible way to implement dynamic routing or not.

I'd be grateful if someone could review my implementation and provide some feedback.

Here's 'Routes.php', this stores the user-defined routes.

// This is the index page. The first route.
Route::set('', function() {
  View::make('Root');
});
// This is a test route, leading to an about-us page.
Route::set('about-us', function() {
  View::make('AboutUs');
});
/*
 * This is an example of a dynamic route. In this example,
 * this route would display a users profile page.
*/
Route::set('user/<1>', function() {
  Route::dyn('user/<1>');
  View::make('UserProfile');
});

The method View::make() has nothing to do with the routing. It's just designed to create the HTML page and the Controller for the page.

The method Route::set() is how I create all routes. Simple routes are created entirely with Route::set(). The dynamic routes are created by executing the closure. Route::set() executes the closure for simple and dynamic routes, for simple routes the closure creates the view and for dynamic routes it swaps <1> for a parameter from the URL and then creates the view.

The reason the syntax is odd, <1>, is because if you want multiple dynamic parameters you can use <2> etc ...

Here's an example

In this example the URL string might look like this user/francis/settings/something-else

Route::set('user/<1>/settings/<2>', function() {
  Route::dyn('user/<1>/settings/<2>');
  View::make('UserProfile');
});

Here's the implementation of the Route::dyn() method

public static function dyn($dyn_routes) {
$route_components = explode('/', $dyn_routes);
$uri_components = explode('/', substr($_SERVER['REQUEST_URI'], strlen(BASEDIR)-1));
for ($i = 0; $i < count($route_components); $i++) {
  if ($i+1 <= count($uri_components)-1) {
    $route_components[$i] = str_replace("<$i>", $uri_components[$i+1], $route_components[$i]);
  }
}
$route = implode($route_components, '/');
self::registerRoute($route);
}

$route_components is what we pass to Route::dyn(). $uri_components is the string we get from the URL, i.e user/francis/settings/something-else. This function converts $route_components so that it is the same as $uri_components. The reason for doing so is that I add all routes to a global array called $Routes. When someone visits a page the URL is checked against the valid routes in the $Routes array.

When the user visits user/francis I want the method Route::set('user/<1>') to run so that the profile page is displayed. It all works with my implementation, I'm just wondering if there is a better way.

Thanks, Francis

\$\endgroup\$
2
  • \$\begingroup\$ your router should not be creating an instance of the view. \$\endgroup\$
    – jeremy
    Commented Jul 31, 2016 at 16:17
  • \$\begingroup\$ @jeremy It's the closure that is doing it, which executes if a route is matched. i.e. acts like a controller. \$\endgroup\$
    – codez
    Commented Aug 8, 2016 at 11:44

1 Answer 1

3
\$\begingroup\$

Looking pretty neat!

But it is missing some important functionality:

  • Ability to define the method of request. There are many kinds of HTTP request methods. Click here to learn more.
  • The fact that you have to call the "dyn" method for dynamic URLs is just not my taste. Other routers are capable of determining if the URL is dynamic or not. This is pretty easy to implement. You could do it like this. You can use REGEX, specifically, you can use the pattern /^<+(.*)+>$/. What you do is, you split the URL with / and use the above REGEX pattern to determine if that particular part of the URL is dynamic or not. You can then get the value by getting the string in the same spot from the typed in URL comparing with the URL route defined.
  • Another great feature would be Request and Response objects. What you would do is, in each request, you pass a Request object with all the HTTP data and that controller method would return an instance of a Response object that would tell the router what to do. Basically, it could be what data to return, HTTP Status Code, etc.

Otherwise, good job!

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for your feedback! I'll definitely look into adding the stuff you mentioned! \$\endgroup\$
    – Francis
    Commented Jul 31, 2016 at 12:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.