AltoRouter icon indicating copy to clipboard operation
AltoRouter copied to clipboard

Group routes with prefix

Open oprichnik opened this issue 10 years ago • 11 comments

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")

oprichnik avatar Jun 16 '14 10:06 oprichnik

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.

koenpunt avatar Jun 16 '14 14:06 koenpunt

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

oprichnik avatar Jun 16 '14 15:06 oprichnik

You can clear the basepath by calling $router->setBasePath('/') which I used in my first example.

koenpunt avatar Jun 16 '14 18:06 koenpunt

@oprichnik @koenpunt @adduc @frosso @niahoo

amandacassandra avatar Aug 16 '14 00:08 amandacassandra

If you want the features symfony gives you, why not use symfony ?

niahoo avatar Aug 16 '14 00:08 niahoo

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..

oprichnik avatar Aug 23 '14 23:08 oprichnik

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 :)

lud avatar Aug 24 '14 17:08 lud

ok fine :) i know, my english vocabulary is a little bit poor :)

oprichnik avatar Aug 24 '14 22:08 oprichnik

@koenpunt Hey, do you happen to have your map_namespacefunction anywhere?

randohinn avatar Mar 21 '18 19:03 randohinn

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.

Lusito avatar Jun 10 '19 14:06 Lusito

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'],
]);

swastikmishra avatar Nov 21 '19 11:11 swastikmishra