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
-
\$\begingroup\$ your router should not be creating an instance of the view. \$\endgroup\$jeremy– jeremy2016年07月31日 16:17:18 +00:00Commented 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– codez2016年08月08日 11:44:02 +00:00Commented Aug 8, 2016 at 11:44
1 Answer 1
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
andResponse
objects. What you would do is, in each request, you pass aRequest
object with all theHTTP
data and that controller method would return an instance of aResponse
object that would tell the router what to do. Basically, it could be whatdata
to return,HTTP Status Code
, etc.
Otherwise, good job!
-
\$\begingroup\$ Thanks for your feedback! I'll definitely look into adding the stuff you mentioned! \$\endgroup\$Francis– Francis2016年07月31日 12:21:57 +00:00Commented Jul 31, 2016 at 12:21