We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

How to use named route instead of default /controller/action

I have named route for those users who forgot theirs passwords,

<?php
$router->add(
    "/forgot-password",
    array(
        'module' => 'frontend',
        'controller' => "session",
        'action' => 'forgotPassword'
    )
);

It's work just fine whe I use URL like this

https://my-site-name.com/forgot-password

But this URL does the same thing

https://my-site-name.com/session/forgotPassword

I suppose that all of my named routes have their clone with canonnical url

https://my-site-name.com/:controller/:action

I realize that it's becasue I setted up some common routes in case when I do not have named route.

<?php

$router = new \Phalcon\Mvc\Router(false);

$router->add(
    "/",
    array(
        'module' => 'frontend',
        'controller' => "index",
        'action' => 'index'
    )
)->setName("homepage");

$router->add(
    "/:controller",
    array(
        'module' => 'frontend',
        "controller" => 1,
        "action"     => "index"
    )
);

$router->add(
    "/:controller/:action",
    array(
        'module' => 'frontend',
        "controller" => 1,
        "action"     => 2
    )
);

$router->add(
    "/:controller/:action/:params",
    array(
        'module' => 'frontend',
        "controller" => 1,
        "action"     => 2,
        "params"     => 3,
    )
);

$router->add(
    "/login",
    array(
        'module' => 'frontend',
        'controller' => "session",
        'action' => 'login'
    )
);

$router->add(
    "/restore-password",
    array(
        'module' => 'frontend',
        'controller' => "session",
        'action' => 'forgotPassword'
    )
);

$router->add(
    "/sign-up",
    array(
        'module' => 'frontend',
        'controller' => "session",
        'action' => 'signup'
    )
);

$router->add(
    "/logout",
    array(
        'module' => 'frontend',
        'controller' => "session",
        'action' => 'logout'
    )
);

$router->add(
    "/forgot-password",
    array(
        'module' => 'frontend',
        'controller' => "session",
        'action' => 'forgotPassword'
    )
);

$router->add(
    "/callback",
    array(
        'module' => 'frontend',
        'controller' => "session",
        'action' => 'callback'
    )
);

$router->add("/admin/:controller/:action/:params", array(
    'module' => 'backend',
    'controller' => 1,
    'action' => 2,
    "params"     => 3,
));
$router->add("/admin/:controller/:action", array(
    'module' => 'backend',
    'controller' => 1,
    'action' => 2,
));

$router->add(
    "/admin/:controller",
    array(
        'module' => 'backend',
        "controller" => 1,
        "action"     => "index"
    )
);

$router->add(
    "/admin",
    array(
        'module' => 'backend',
        'controller' => "index",
        'action' => 'index'
    )
);

$router->removeExtraSlashes(true);

return $router;

So my question is easy. How can I prevent application use common route (ex. /session/forgotPassword) and use the named route (ex. /forgot-password) in case when named route is exist in route's definition.

Thanks.

edited Nov '14

Related to documentation https://docs.phalcon.io/en/latest/reference/routing.html#default-behavior

<?php

// Create the router without default routes
$router = new \Phalcon\Mvc\Router(false);

Edit: I just see that you have this already but you have defined the default route again

<?php
$router->add(
    "/:controller/:action",
    array(
        'module' => 'frontend',
        "controller" => 1,
        "action"     => 2
    )
);

I think in this case you cannot prevent Phalcon from using both routes. One way can be implementing a event handler for beforeExecuteRoute and check it there.



12.2k

Related to documentation https://docs.phalcon.io/en/latest/reference/routing.html#default-behavior

<?php

// Create the router without default routes
$router = new \Phalcon\Mvc\Router(false);

yeap, and if you take a look to my code this options is same as you've suggested just now.

this is overided by my rules listed in my routes definitions.

I see only one solution, create named routes for any part of my application, but I hope that I can do more smartes thing intestead of fringerprinting.

Thanks



11.2k

There are only two ways to avoid that a valid /:controller/:action works:

1) Remove the /:controller/:action route

2) Overload the route for the valid controller/action to one that calls the error page. Ex:

$router->add(
    "/:controller/:action",
    array(
        'module' => 'frontend',
        "controller" => 1,
        "action"     => 2
    )
);

// ...

$router->add(
    "/session/forgotPassword",
    array(
        'module' => 'frontend',
        "controller" => 'error',
        "action"     => 'notfound'
    )
);


12.2k

There are only two ways to avoid that a valid /:controller/:action works:

1) Remove the /:controller/:action route

2) Overload the route for the valid controller/action to one that calls the error page. Ex:

Yes this is what I want to avoid. If i will have 2 controllers it will just fine, but I already had 5 controllers and this amount will grow, because it will be a big application.

Seems like I have to do a some kind of comparriosions in beforeRouteExecute method, to figure out is this route has name defined or not.

But I doubt about this, because I'm new in Phalcon, and maybe just do not know some others ways to achieve what I want.

Thanks.



11.2k

There are only two ways to avoid that a valid /:controller/:action works:

1) Remove the /:controller/:action route

2) Overload the route for the valid controller/action to one that calls the error page. Ex:

Yes this is what I want to avoid. If i will have 2 controllers it will just fine, but I already had 5 controllers and this amount will grow, because it will be a big application.

Seems like I have to do a some kind of comparriosions in beforeRouteExecute method, to figure out is this route has name defined or not.

But I doubt about this, because I'm new in Phalcon, and maybe just do not know some others ways to achieve what I want.

Thanks.

I would recomend you to simply not use the "default route" and create a route for each action.



12.2k

I just came with the next rought solution.

  1. I have only one named route (homepage);
  2. I do not have named route for 'forgot-password' page;

So first I have to set name for this route

<?php
$router = new \Phalcon\Mvc\Router(false);
$router->add(
    "/forgot-password",
    array(
        'module' => 'frontend',
        'controller' => "session",
        'action' => 'forgotPassword'
    )
)->setName('forgot-password');

$router->add(
    "/:controller/:action",
    array(
        'module' => 'frontend',
        "controller" => 1,
        "action"     => 2
    )
);

Than I tested this

<?php

$testRoutes = array(
    '/session/forgotPassword',
    '/forgot-password'
);

//Testing each route
foreach ($testRoutes as $testRoute) {

    //Handle the route
    $router->handle($testRoute);

    echo 'Testing ', $testRoute, '<br>';
    $routeName = $router->getMatchedRoute()->getName();
    //Check if some route was matched
    if ($router->wasMatched() && !empty($routeName)) {
        echo 'Route Name: ', $router->getMatchedRoute()->getName(), '<br>';
        echo 'Module: ', $router->getModuleName(), '<br>';
        echo 'Controller: ', $router->getControllerName(), '<br>';
        echo 'Action: ', $router->getActionName(), '<br>';
    } else {
        echo 'The route wasn\'t matched by any route<br>';
    }
    echo '<br>';

}
Output is:

Testing /session/forgotPassword
The route wasn't matched by any route

Testing /forgot-password
Route Name: forgot-password
Module: frontend
Controller: session
Action: forgotPassword

Still want to find more elegant solution.