Remove `Route` Class
taufik-nurrohman opened this issue · comments
From the very beginning, class Route
is actually just a syntactic sugar for conditional on the $url->path
value.
Both of the commands below can be considered identical:
Route::set("", function() { … });
Route::set('*', function($path) { … });
Route::set('product/:id', function($id) { … });
Route::start();
$route = trim($url->path, '/');
$fn = function() {};
$lot = [];
if ("" === $route) {
$fn = function() { … };
}
if ("" !== $route) {
$fn = function($path) { … };
$lot = [$route];
}
if (preg_match('/^product\/([^\/]*)$/', $route, $m)) {
$fn = function($id) { … };
$lot = [$m[1]];
}
call_user_func($fn, $lot);
Just because the route is executed at the end and has a function stack feature, it becomes a safer option for extensions to add custom pages since extensions can control the route function execution priority by adding a stack value to the route definition so that the core system can execute those functions in order.
Do you know what else has a function stack feature? Hooks!
Yes, we can replace Route
class completely with Hook
! Hook name is likely to last longer since even WordPress still using the term to this day. But I need a good name to associate route-related hooks on the system as a built-in feature. The best hook name candidate for now is probably route
. This name will certainly be harmonious when paired with content
.
Hook::set('route', function($route) { … }, 10);
Now I need a way to parse the $route
component as in Route
. It must be neat and can auto-parse numeric part into a real number.
Creating namespaces for each route might make it a bit easier to develop. Each extension can then add their own route hooks into the main route hook. This will automatically create the impression of having a group feature on the route mechanism without making it complicated:
<?php
// `.\lot\x\page\index.php`
Hook::set('route', function($route) {
Hook::fire('route.page', [$route], $this);
}, 10);
<?php
// `.\lot\x\user\index.php`
Hook::set('route', function($route) {
if ("" === $route) {
return;
}
$chops = explode('/', $route);
if ('user' === array_shift($chops)) {
if (1 === count($chops)) {
// `http://127.0.0.1/user/taufik-nurrohman`
Hook::fire('route.user', [$chops[0]], $this);
} else {
// `http://127.0.0.1/user`
Hook::fire('route.user', [null], $this);
}
} else {
// Default to the page route
Hook::fire('route.page', [$route], $this);
}
}, 9);
<?php
// `.\lot\x\tag\index.php`
Hook::set('route', function($route) {
if ("" === $route || 0 === substr_count($route, '/')) {
return;
}
$chops = explode('/', $path);
$tag = array_pop($chops);
$path = array_pop($chops);
if ('tag' === $path && $tag) {
Hook::fire('route.tag', [$tag], $this);
} else {
// Default to the page route
Hook::fire('route.page', [$route], $this);
}
}, 9);
Route::hit()
method can be performed simply by pushing more hooks with a higher stack:
Hook::set('route.page', function($route) { … }, 1); // This should run on top of the default `route.page` hook