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

Making an action accept only integer parameters; dispatcher request

Hello!

I would like to follow the automatic MVC routing schema (/controller/action/parameters), but for some specific actions, I should only accept integer parameters. Is it possible to achieve such a behavior while sticking to the MVC routing schema as a fallback for other actions?

Also, I'm currently trying to separate the DB functionality from the frontend into an API controller. Is it possible to request data from other controllers using the dispatcher? (In this case, I'd like to request some data from the ApiController, using the UsersController.)

edited Aug '15

Szasz!

Regarding your first question, it is possible:

$router->add("/:controller/:action/:id", [
    'id' => 3,
]);

You can also use standard regexp patterns:

$router->add("/:controller/:action/([\d]+)", [
    'id' => 3,
]);

Routing schemas are checked in the order of definition, so if you then add this:

$router->add("/:controller/:action/:params", [
]);

it will still route as standard if the third part is not an integer. More info here: https://docs.phalcon.io/en/latest/reference/routing.html

As for the second question, it's not possible. You could technically create an ApiController instance in the UsersController, but because it's a different module the whole dependency tree also has to be setup.

I'm using common models for every module and place those functionalities there as static methods.



1.4k
edited Aug '15

Szasz!

Regarding your first question, it is possible:

$router->add("/:controller/:action/:id", [
  'id' => 3,
]);

You can also use standard regexp patterns:

$router->add("/:controller/:action/([\d]+)", [
  'id' => 3,
]);

Routing schemas are checked in the order of definition, so if you then add this:

$router->add("/:controller/:action/:params", [
]);

it will still route as standard if the third part is not an integer. More info here: https://docs.phalcon.io/en/latest/reference/routing.html

As for the second question, it's not possible. You could technically create an ApiController instance in the UsersController, but because it's a different module the whole dependency tree also has to be setup.

I'm using common models for every module and place those functionalities there as static methods.

My problem is that the last routing would still forward the request to the action which should only take integer params. As there is no way to exclude a routing rule for specific paths (AFAIK), may I ask what you would prefer as the best way of validating parameters?

  • if (!ctype_digit($param)) return;
  • Using your forwarding method with $this->dispatcher->getParam("id");

Performance would also be important.

edited Aug '15

It's strange that the :id rule is executed instead of the :params when it's non-numeric... you could paste the full routing set-up if you want, BUT...

If you don't dispatch in your action depending on the type of $param just halt or error report if it's not integer, using a single $router->add("/:controller/:action/:params"); route is preferable performance-wise; there are fewer route rules to check against.



125.8k
Accepted
answer

There is an order to the routes that match. Phalcon matches the last rule that was added. So, say your setup is like this:

// Generic rule
$router->add("/:controller/:action/:id", [
    'id' => 3,
]);

// Integer rule
$router->add("/:controller/:action/(:int)", [
    'id' => 3,
]);

If you have a url like: /cars/list/honda, Phalcon will first look at the Integer rule, determine that it doesn't match, then move up to the Generic rule. If you have a url like : cars/buy/12885, Phalcon will again first look at the Integer rule, determine that it does match, then route the request to the relevant controller.

You say you have specific actions that should only accept integers. In that case, I'd recommend making specific routes for those actions, and add them last, like:

$router->add("/(cars)/(buy)/(:int)", [
    'id' => 3,
]);

Sorry about my mistake, @quasipickle is right:

Since you can add many routes as you need using add(), the order in which routes are added indicate their relevance, latest routes added have more relevance than first added. Internally, all defined routes are traversed in reverse order until Phalcon\Mvc\Router finds the one that matches the given URI and processes it, while ignoring the rest.

https://docs.phalcon.io/en/latest/reference/routing.html



1.4k

Thank you for the answers, both of you are awesome! :)