AltoRouter
AltoRouter copied to clipboard
Group routes with prefix
As an enhancement, it would be great to add a "RouteGroup" which contains an array of routes and a prefix for all (e.g to avoid repeating "/admin")
You can already achieve this with setBasePath
:
$router->map('GET', '/', 'website#index');
$router->setBasePath('/admin');
$router->map('GET', '/', 'admin#index');
$router->setBasePath('/');
$router->map('GET', '/[*:path]', 'pages#show');
But I've actually extended AltoRouter with a map_namespace
method, which keeps track of namespace and path recursively. So I can use it like this:
$router->map('GET', '/', 'website#index');
$router->map_namespace('admin', function($router){
# => /admin which will direct Admin\AdminController#index
$router->map('GET', '/', 'admin#index');
# => /admin/modules which will direct Admin\ModulesController#index
$router->map('GET', '/modules', 'modules#index');
$router->map_namespace('modules', function($router){
# => /admin/modules/pages which will direct to Admin\Modules\PagesController#index
$router->map('GET', '/pages', 'page#index');
});
});
But this is very dependent on the actual implementation. Although I could see the use of this with a map_path
method.
Right but that way you cannot change the prefix (for all routes you set "/admin" as prefix) after having set it. Maybe just have a $children property like Symfony's RouteCollection: http://api.symfony.com/2.0/Symfony/Component/Routing/RouteCollection.html
You can clear the basepath by calling $router->setBasePath('/')
which I used in my first example.
@oprichnik @koenpunt @adduc @frosso @niahoo
If you want the features symfony gives you, why not use symfony ?
I'm not complaining, just trying to make things better, Symfony has its lacks too if you really want to know. I was giving my opinion with arguments, beat them, not me..
Sorry if my post felt rude, I'm not beating you :) I meant tha you can use Symfony's router, not Symfony as a whole. I don't know if it lacks many things, but since AltoRouter is very simple, I can't see features we have that Symfony doesn't.
Have a nice day :)
ok fine :) i know, my english vocabulary is a little bit poor :)
@koenpunt Hey, do you happen to have your map_namespace
function anywhere?
If anyone is looking for a solution, I'd like to offer my current solution. I'm just starting with AltoRouter, so maybe this approach has its flaws, but for now it seems to work good with my current paths:
// This one is just for convenience (skip or adjust as needed):
function crudRoute(string $controller, string $idSuffix='/[i:id]') {
return [
['GET', 's', "$controller#actionListGET"],
['POST', '', "$controller#actionPOST"],
['GET|PUT|DELETE', $idSuffix, "$controller#action{METHOD}"]
];
}
// This is the one that maps a tree to a flat array, which can be used by altorouter
function composeRoutes(string $prefix, array $tree, array &$result = []) {
foreach($tree as $key => $value) {
if (is_string($key))
composeRoutes($prefix . $key, $value, $result);
else {
$value[1] = $prefix . $value[1];
$result []= $value;
}
}
return $result;
}
// Example use:
$routes = composeRoutes('/basefolder'), [
'/api' => [
['GET', '/content/text', 'api\ContentController#actionTextGET'],
['GET', '/content/row', 'api\ContentController#actionRowGET'],
['GET', '/content/global', 'api\ContentController#actionGlobalListGET'],
'/content' => crudRoute('api\ContentController'),
'/domain' => crudRoute('api\DomainController', '/[*:name]'),
'/file' => crudRoute('api\FileController'),
'/log-error' => [
['GET', 's/count', 'api\LogErrorController#actionCountGET'],
['GET', 's', 'api\LogErrorController#actionListGET'],
['DELETE', 's', 'api\LogErrorController#actionListDELETE'],
['DELETE', '/[i:id]', 'api\LogErrorController#actionDELETE']
],
['PUT', '/page/[i:id]/parent', 'api\PageController#actionParentPUT'],
['PUT', '/page/[i:id]/content', 'api\PageController#actionContentPUT'],
'/page' => crudRoute('api\PageController'),
'/session' => [
['GET', '/events', 'api\SessionController#actionEventsGET'],
['POST', '/autoLogin', 'api\SessionController#actionAutoLoginPOST'],
['POST', '/login', 'api\SessionController#actionLoginPOST']
],
['GET|PUT', '/site/[i:id]/menus', 'api\SiteController#actionMenus{METHOD}'],
'/site' => crudRoute('api\SiteController'),
'/user' => crudRoute('api\UserController', '/[i:id]?'),
],
['GET', '/admin/[**]?', 'AdminController#actionGET'],
['GET', '/file/download/[i:id]/[**]?', 'FileController#actionDownloadGET'],
['GET', '/file/image/[i:id]/[**]?', 'FileController#actionImageGET'],
['GET', '/page/[i:id]/[**]?', 'PageController#actionGET'],
['GET', '/', 'PageController#actionRootGET']
]);
If you are wondering about the {METHOD}
, I do some replacement after getting the current route and then replace that string with the actual request method.
I guess this is an old post, but still if anyone comes up looking for an answer.
Add the following function in AltoRouter.php
public function group($prefix, $routes){
foreach($routes as $k=>$r)
$routes[$k][1] = $prefix.$r[1];
$this->addRoutes($routes);
}
And you can use it in the following way
$Router->group('/api', [
['POST', '/auth/login', 'LoginController@login'],
['GET', '/auth/logout', 'LoginController@logout'],
['POST', '/auth/register', 'RegisterController@register'],
['POST', '/auth/forgot', 'ForgotPasswordController@forgot'],
]);