Routing

The router component allows you to define routes that are mapped to controllers or handlers that should receive the request. A router simply parses a URI to determine this information. The router has two modes: MVC mode and match-only mode. The first mode is ideal for working with MVC applications.

Defining Routes

Phalcon\Mvc\Router provides advanced routing capabilities. In MVC mode, you can define routes and map them to controllers/actions that you require. A route is defined as follows:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. // Create the router
  4. $router = new Router();
  5. // Define a route
  6. $router->add(
  7. '/admin/users/my-profile',
  8. [
  9. 'controller' => 'users',
  10. 'action' => 'profile',
  11. ]
  12. );
  13. // Another route
  14. $router->add(
  15. '/admin/users/change-password',
  16. [
  17. 'controller' => 'users',
  18. 'action' => 'changePassword',
  19. ]
  20. );
  21. $router->handle();

The first parameter of the add() method is the pattern you want to match and, optionally, the second parameter is a set of paths.In this case, if the URI is /admin/users/my-profile, then the users controller with its action profile will be executed. It’s important to remember that the router does not execute the controller and action, it only collects this information to inform the correct component (i.e. Phalcon\Mvc\Dispatcher) that this is the controller/action it should execute.

An application can have many paths and defining routes one by one can be a cumbersome task. In these cases we can create more flexible routes:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. // Create the router
  4. $router = new Router();
  5. // Define a route
  6. $router->add(
  7. '/admin/:controller/a/:action/:params',
  8. [
  9. 'controller' => 1,
  10. 'action' => 2,
  11. 'params' => 3,
  12. ]
  13. );

In the example above, we’re using wildcards to make a route valid for many URIs. For example, by accessing the following URL (/admin/users/a/delete/dave/301) would produce:

ControllerActionParameterParameter
usersdeletedave301

The add() method receives a pattern that can optionally have predefined placeholders and regular expression modifiers. All the routing patterns must start with a forward slash character (/). The regular expression syntax used is the same as the PCRE regular expressions. Note that, it is not necessary to add regular expression delimiters. All route patterns are case-insensitive.

The second parameter defines how the matched parts should bind to the controller/action/parameters. Matching parts are placeholders or subpatterns delimited by parentheses (round brackets). In the example given above, the first subpattern matched (:controller) is the controller part of the route, the second the action and so on.

These placeholders help writing regular expressions that are more readable for developers and easier to understand. The following placeholders are supported:

PlaceholderRegular ExpressionUsage
/:module/([a-zA-Z0-9_-]+)Matches a valid module name with alpha-numeric characters only
/:controller/([a-zA-Z0-9_-]+)Matches a valid controller name with alpha-numeric characters only
/:action/([a-zA-Z0-9-]+)Matches a valid action name with alpha-numeric characters only
/:params(/.)Matches a list of optional words separated by slashes. Only use this placeholder at the end of a route
/:namespace/([a-zA-Z0-9\-]+)Matches a single level namespace name
/:int/([0-9]+)Matches an integer parameter

Controller names are camelized, this means that characters (-) and (_) are removed and the next character is uppercased. For instance, some_controller is converted to SomeController.

Since you can add many routes as you need using the add() method, 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.

Parameters with Names

The example below demonstrates how to define names to route parameters:

  1. <?php
  2. $router->add(
  3. '/news/([0-9]{4})/([0-9]{2})/([0-9]{2})/:params',
  4. [
  5. 'controller' => 'posts',
  6. 'action' => 'show',
  7. 'year' => 1, // ([0-9]{4})
  8. 'month' => 2, // ([0-9]{2})
  9. 'day' => 3, // ([0-9]{2})
  10. 'params' => 4, // :params
  11. ]
  12. );

In the above example, the route doesn’t define a controller or action part. These parts are replaced with fixed values (posts and show). The user will not know the controller that is really dispatched by the request. Inside the controller, those named parameters can be accessed as follows:

  1. <?php
  2. use Phalcon\Mvc\Controller;
  3. class PostsController extends Controller
  4. {
  5. public function indexAction()
  6. {
  7. }
  8. public function showAction()
  9. {
  10. // Get 'year' parameter
  11. $year = $this->dispatcher->getParam('year');
  12. // Get 'month' parameter
  13. $month = $this->dispatcher->getParam('month');
  14. // Get 'day' parameter
  15. $day = $this->dispatcher->getParam('day');
  16. // ...
  17. }
  18. }

Note that the values of the parameters are obtained from the dispatcher. This happens because it is the component that finally interacts with the drivers of your application. Moreover, there is also another way to create named parameters as part of the pattern:

  1. <?php
  2. $router->add(
  3. '/documentation/{chapter}/{name}.{type:[a-z]+}',
  4. [
  5. 'controller' => 'documentation',
  6. 'action' => 'show',
  7. ]
  8. );

You can access their values in the same way as before:

  1. <?php
  2. use Phalcon\Mvc\Controller;
  3. class DocumentationController extends Controller
  4. {
  5. public function showAction()
  6. {
  7. // Get 'name' parameter
  8. $name = $this->dispatcher->getParam('name');
  9. // Get 'type' parameter
  10. $type = $this->dispatcher->getParam('type');
  11. // ...
  12. }
  13. }

Short Syntax

If you don’t like using an array to define the route paths, an alternative syntax is also available. The following examples produce the same result:

  1. <?php
  2. // Short form
  3. $router->add(
  4. '/posts/{year:[0-9]+}/{title:[a-z\-]+}',
  5. 'Posts::show'
  6. );
  7. // Array form
  8. $router->add(
  9. '/posts/([0-9]+)/([a-z\-]+)',
  10. [
  11. 'controller' => 'posts',
  12. 'action' => 'show',
  13. 'year' => 1,
  14. 'title' => 2,
  15. ]
  16. );

Mixing Array and Short Syntax

Array and short syntax can be mixed to define a route, in this case note that named parameters automatically are added to the route paths according to the position on which they were defined:

  1. <?php
  2. // First position must be skipped because it is used for
  3. // the named parameter 'country'
  4. $router->add(
  5. '/news/{country:[a-z]{2}}/([a-z+])/([a-z\-+])',
  6. [
  7. 'section' => 2, // Positions start with 2
  8. 'article' => 3,
  9. ]
  10. );

Routing to Modules

You can define routes whose paths include modules. This is specially suitable to multi-module applications. It’s possible define a default route that includes a module wildcard:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. $router = new Router(false);
  4. $router->add(
  5. '/:module/:controller/:action/:params',
  6. [
  7. 'module' => 1,
  8. 'controller' => 2,
  9. 'action' => 3,
  10. 'params' => 4,
  11. ]
  12. );

In this case, the route always must have the module name as part of the URL. For example, the following URL: /admin/users/edit/sonny, will be processed as:

ModuleControllerActionParameter
adminuserseditsonny

Or you can bind specific routes to specific modules:

  1. <?php
  2. $router->add(
  3. '/login',
  4. [
  5. 'module' => 'backend',
  6. 'controller' => 'login',
  7. 'action' => 'index',
  8. ]
  9. );
  10. $router->add(
  11. '/products/:action',
  12. [
  13. 'module' => 'frontend',
  14. 'controller' => 'products',
  15. 'action' => 1,
  16. ]
  17. );

Or bind them to specific namespaces:

  1. <?php
  2. $router->add(
  3. '/:namespace/login',
  4. [
  5. 'namespace' => 1,
  6. 'controller' => 'login',
  7. 'action' => 'index',
  8. ]
  9. );

Namespaces/class names must be passed separated:

  1. <?php
  2. $router->add(
  3. '/login',
  4. [
  5. 'namespace' => 'Backend\Controllers',
  6. 'controller' => 'login',
  7. 'action' => 'index',
  8. ]
  9. );

HTTP Method Restrictions

When you add a route using simply add(), the route will be enabled for any HTTP method. Sometimes we can restrict a route to a specific method, this is especially useful when creating RESTful applications:

  1. <?php
  2. // This route only will be matched if the HTTP method is GET
  3. $router->addGet(
  4. '/products/edit/{id}',
  5. 'Products::edit'
  6. );
  7. // This route only will be matched if the HTTP method is POST
  8. $router->addPost(
  9. '/products/save',
  10. 'Products::save'
  11. );
  12. // This route will be matched if the HTTP method is POST or PUT
  13. $router->add(
  14. '/products/update',
  15. 'Products::update'
  16. )->via(
  17. [
  18. 'POST',
  19. 'PUT',
  20. ]
  21. );

Using conversors

Conversors allow you to freely transform the route’s parameters before passing them to the dispatcher. The following examples show how to use them:

  1. <?php
  2. // The action name allows dashes, an action can be: /products/new-ipod-nano-4-generation
  3. $route = $router->add(
  4. '/products/{slug:[a-z\-]+}',
  5. [
  6. 'controller' => 'products',
  7. 'action' => 'show',
  8. ]
  9. );
  10. $route->convert(
  11. 'slug',
  12. function ($slug) {
  13. // Transform the slug removing the dashes
  14. return str_replace('-', '', $slug);
  15. }
  16. );

Another use case for conversors is binding a model into a route. This allows the model to be passed into the defined action directly:

  1. <?php
  2. // This example works off the assumption that the ID is being used as parameter in the url: /products/4
  3. $route = $router->add(
  4. '/products/{id}',
  5. [
  6. 'controller' => 'products',
  7. 'action' => 'show',
  8. ]
  9. );
  10. $route->convert(
  11. 'id',
  12. function ($id) {
  13. // Fetch the model
  14. return Product::findFirstById($id);
  15. }
  16. );

Groups of Routes

If a set of routes have common paths they can be grouped to easily maintain them:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. use Phalcon\Mvc\Router\Group as RouterGroup;
  4. $router = new Router();
  5. // Create a group with a common module and controller
  6. $blog = new RouterGroup(
  7. [
  8. 'module' => 'blog',
  9. 'controller' => 'index',
  10. ]
  11. );
  12. // All the routes start with /blog
  13. $blog->setPrefix('/blog');
  14. // Add a route to the group
  15. $blog->add(
  16. '/save',
  17. [
  18. 'action' => 'save',
  19. ]
  20. );
  21. // Add another route to the group
  22. $blog->add(
  23. '/edit/{id}',
  24. [
  25. 'action' => 'edit',
  26. ]
  27. );
  28. // This route maps to a controller different than the default
  29. $blog->add(
  30. '/blog',
  31. [
  32. 'controller' => 'blog',
  33. 'action' => 'index',
  34. ]
  35. );
  36. // Add the group to the router
  37. $router->mount($blog);

You can move groups of routes to separate files in order to improve the organization and code reusing in the application:

  1. <?php
  2. use Phalcon\Mvc\Router\Group as RouterGroup;
  3. class BlogRoutes extends RouterGroup
  4. {
  5. public function initialize()
  6. {
  7. // Default paths
  8. $this->setPaths(
  9. [
  10. 'module' => 'blog',
  11. 'namespace' => 'Blog\Controllers',
  12. ]
  13. );
  14. // All the routes start with /blog
  15. $this->setPrefix('/blog');
  16. // Add a route to the group
  17. $this->add(
  18. '/save',
  19. [
  20. 'action' => 'save',
  21. ]
  22. );
  23. // Add another route to the group
  24. $this->add(
  25. '/edit/{id}',
  26. [
  27. 'action' => 'edit',
  28. ]
  29. );
  30. // This route maps to a controller different than the default
  31. $this->add(
  32. '/blog',
  33. [
  34. 'controller' => 'blog',
  35. 'action' => 'index',
  36. ]
  37. );
  38. }
  39. }

Then mount the group in the router:

  1. <?php
  2. // Add the group to the router
  3. $router->mount(
  4. new BlogRoutes()
  5. );

Matching Routes

A valid URI must be passed to the Router so that it can process it and find a matching route. By default, the routing URI is taken from the $_GET['_url'] variable that is created by the rewrite engine module. A couple of rewrite rules that work very well with Phalcon are:

  1. RewriteEngine On
  2. RewriteCond %{REQUEST_FILENAME} !-d
  3. RewriteCond %{REQUEST_FILENAME} !-f
  4. RewriteRule ^((?s).*)$ index.php?_url=/$1 [QSA,L]

In this configuration, any requests to files or folders that don’t exist will be sent to index.php. The following example shows how to use this component in stand-alone mode:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. // Creating a router
  4. $router = new Router();
  5. // Define routes here if any
  6. // ...
  7. // Taking URI from $_GET['_url']
  8. $router->handle();
  9. // Or Setting the URI value directly
  10. $router->handle('/employees/edit/17');
  11. // Getting the processed controller
  12. echo $router->getControllerName();
  13. // Getting the processed action
  14. echo $router->getActionName();
  15. // Get the matched route
  16. $route = $router->getMatchedRoute();

Naming Routes

Each route that is added to the router is stored internally as a Phalcon\Mvc\Router\Route object. That class encapsulates all the details of each route. For instance, we can give a name to a path to identify it uniquely in our application. This is especially useful if you want to create URLs from it.

  1. <?php
  2. $route = $router->add(
  3. '/posts/{year}/{title}',
  4. 'Posts::show'
  5. );
  6. $route->setName('show-posts');

Then, using for example the component Phalcon\Mvc\Url we can build routes from its name:

  1. <?php
  2. // Returns /posts/2012/phalcon-1-0-released
  3. echo $url->get(
  4. [
  5. 'for' => 'show-posts',
  6. 'year' => '2012',
  7. 'title' => 'phalcon-1-0-released',
  8. ]
  9. );

Usage Examples

The following are examples of custom routes:

  1. <?php
  2. // Matches '/system/admin/a/edit/7001'
  3. $router->add(
  4. '/system/:controller/a/:action/:params',
  5. [
  6. 'controller' => 1,
  7. 'action' => 2,
  8. 'params' => 3,
  9. ]
  10. );
  11. // Matches '/es/news'
  12. $router->add(
  13. '/([a-z]{2})/:controller',
  14. [
  15. 'controller' => 2,
  16. 'action' => 'index',
  17. 'language' => 1,
  18. ]
  19. );
  20. // Matches '/es/news'
  21. $router->add(
  22. '/{language:[a-z]{2}}/:controller',
  23. [
  24. 'controller' => 2,
  25. 'action' => 'index',
  26. ]
  27. );
  28. // Matches '/admin/posts/edit/100'
  29. $router->add(
  30. '/admin/:controller/:action/:int',
  31. [
  32. 'controller' => 1,
  33. 'action' => 2,
  34. 'id' => 3,
  35. ]
  36. );
  37. // Matches '/posts/2015/02/some-cool-content'
  38. $router->add(
  39. '/posts/([0-9]{4})/([0-9]{2})/([a-z\-]+)',
  40. [
  41. 'controller' => 'posts',
  42. 'action' => 'show',
  43. 'year' => 1,
  44. 'month' => 2,
  45. 'title' => 3,
  46. ]
  47. );
  48. // Matches '/manual/en/translate.adapter.html'
  49. $router->add(
  50. '/manual/([a-z]{2})/([a-z\.]+)\.html',
  51. [
  52. 'controller' => 'manual',
  53. 'action' => 'show',
  54. 'language' => 1,
  55. 'file' => 2,
  56. ]
  57. );
  58. // Matches /feed/fr/le-robots-hot-news.atom
  59. $router->add(
  60. '/feed/{lang:[a-z]+}/{blog:[a-z\-]+}\.{type:[a-z\-]+}',
  61. 'Feed::get'
  62. );
  63. // Matches /api/v1/users/peter.json
  64. $router->add(
  65. '/api/(v1|v2)/{method:[a-z]+}/{param:[a-z]+}\.(json|xml)',
  66. [
  67. 'controller' => 'api',
  68. 'version' => 1,
  69. 'format' => 4,
  70. ]
  71. );
Beware of characters allowed in regular expression for controllers and namespaces. As these become class names and in turn they’re passed through the file system could be used by attackers to read unauthorized files. A safe regular expression is: /([a-zA-Z0-9_-]+)

Default Behavior

Phalcon\Mvc\Router has a default behavior that provides a very simple routing that always expects a URI that matches the following pattern: /:controller/:action/:params

For example, for a URL like this http://phalconphp.com/documentation/show/about.html, this router will translate it as follows:

ControllerActionParameter
documentationshowabout.html

If you don’t want the router to have this behavior, you must create the router passing false as the first parameter:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. // Create the router without default routes
  4. $router = new Router(false);

Setting the default route

When your application is accessed without any route, the ‘/’ route is used to determine what paths must be used to show the initial page in your website/application:

  1. <?php
  2. $router->add(
  3. '/',
  4. [
  5. 'controller' => 'index',
  6. 'action' => 'index',
  7. ]
  8. );

Not Found Paths

If none of the routes specified in the router are matched, you can define a group of paths to be used in this scenario:

  1. <?php
  2. // Set 404 paths
  3. $router->notFound(
  4. [
  5. 'controller' => 'index',
  6. 'action' => 'route404',
  7. ]
  8. );

This is typically for an Error 404 page.

This will only work if the router was created without default routes: $router = Phalcon\Mvc\Router(FALSE);

Setting default paths

It’s possible to define default values for the module, controller or action. When a route is missing any of those paths they can be automatically filled by the router:

  1. <?php
  2. // Setting a specific default
  3. $router->setDefaultModule('backend');
  4. $router->setDefaultNamespace('Backend\Controllers');
  5. $router->setDefaultController('index');
  6. $router->setDefaultAction('index');
  7. // Using an array
  8. $router->setDefaults(
  9. [
  10. 'controller' => 'index',
  11. 'action' => 'index',
  12. ]
  13. );

Dealing with extra/trailing slashes

Sometimes a route could be accessed with extra/trailing slashes. Those extra slashes would lead to produce a not-found status in the dispatcher. You can set up the router to automatically remove the slashes from the end of handled route:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. $router = new Router();
  4. // Remove trailing slashes automatically
  5. $router->removeExtraSlashes(true);

Or, you can modify specific routes to optionally accept trailing slashes:

  1. <?php
  2. // The [/]{0,1} allows this route to have optionally have a trailing slash
  3. $router->add(
  4. '/{language:[a-z]{2}}/:controller[/]{0,1}',
  5. [
  6. 'controller' => 2,
  7. 'action' => 'index',
  8. ]
  9. );

Match Callbacks

Sometimes, routes should only be matched if they meet specific conditions. You can add arbitrary conditions to routes using the beforeMatch() callback. If this function return false, the route will be treated as non-matched:

  1. <?php
  2. $route = $router->add('/login',
  3. [
  4. 'module' => 'admin',
  5. 'controller' => 'session',
  6. ]
  7. );
  8. $route->beforeMatch(
  9. function ($uri, $route) {
  10. // Check if the request was made with Ajax
  11. if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') {
  12. return false;
  13. }
  14. return true;
  15. }
  16. );

You can re-use these extra conditions in classes:

  1. <?php
  2. class AjaxFilter
  3. {
  4. public function check()
  5. {
  6. return $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
  7. }
  8. }

And use this class instead of the anonymous function:

  1. <?php
  2. $route = $router->add(
  3. '/get/info/{id}',
  4. [
  5. 'controller' => 'products',
  6. 'action' => 'info',
  7. ]
  8. );
  9. $route->beforeMatch(
  10. [
  11. new AjaxFilter(),
  12. 'check'
  13. ]
  14. );

As of Phalcon 3, there is another way to check this:

  1. <?php
  2. $route = $router->add(
  3. '/login',
  4. [
  5. 'module' => 'admin',
  6. 'controller' => 'session',
  7. ]
  8. );
  9. $route->beforeMatch(
  10. function ($uri, $route) {
  11. /**
  12. * @var string $uri
  13. * @var \Phalcon\Mvc\Router\Route $route
  14. * @var \Phalcon\DiInterface $this
  15. * @var \Phalcon\Http\Request $request
  16. */
  17. $request = $this->getShared('request');
  18. // Check if the request was made with Ajax
  19. return $request->isAjax();
  20. }
  21. );

Hostname Constraints

The router allows you to set hostname constraints, this means that specific routes or a group of routes can be restricted to only match if the route also meets the hostname constraint:

  1. <?php
  2. $route = $router->add(
  3. '/login',
  4. [
  5. 'module' => 'admin',
  6. 'controller' => 'session',
  7. 'action' => 'login',
  8. ]
  9. );
  10. $route->setHostName('admin.company.com');

The hostname can also be passed as a regular expressions:

  1. <?php
  2. $route = $router->add(
  3. '/login',
  4. [
  5. 'module' => 'admin',
  6. 'controller' => 'session',
  7. 'action' => 'login',
  8. ]
  9. );
  10. $route->setHostName('([a-z]+).company.com');

In groups of routes you can set up a hostname constraint that apply for every route in the group:

  1. <?php
  2. use Phalcon\Mvc\Router\Group as RouterGroup;
  3. // Create a group with a common module and controller
  4. $blog = new RouterGroup(
  5. [
  6. 'module' => 'blog',
  7. 'controller' => 'posts',
  8. ]
  9. );
  10. // Hostname restriction
  11. $blog->setHostName('blog.mycompany.com');
  12. // All the routes start with /blog
  13. $blog->setPrefix('/blog');
  14. // Default route
  15. $blog->add(
  16. '/',
  17. [
  18. 'action' => 'index',
  19. ]
  20. );
  21. // Add a route to the group
  22. $blog->add(
  23. '/save',
  24. [
  25. 'action' => 'save',
  26. ]
  27. );
  28. // Add another route to the group
  29. $blog->add(
  30. '/edit/{id}',
  31. [
  32. 'action' => 'edit',
  33. ]
  34. );
  35. // Add the group to the router
  36. $router->mount($blog);

URI Sources

By default the URI information is obtained from the $_GET['_url'] variable, this is passed by the Rewrite-Engine to Phalcon, you can also use $_SERVER['REQUEST_URI'] if required:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. // ...
  4. // Use $_GET['_url'] (default)
  5. $router->setUriSource(
  6. Router::URI_SOURCE_GET_URL
  7. );
  8. // Use $_SERVER['REQUEST_URI']
  9. $router->setUriSource(
  10. Router::URI_SOURCE_SERVER_REQUEST_URI
  11. );

Or you can manually pass a URI to the handle() method:

  1. <?php
  2. $router->handle('/some/route/to/handle');
Please note that using Router::URI_SOURCE_GET_URL automatically decodes the Uri, because it is based on the $_REQUEST superglobal. However, for the time being, using Router::URI_SOURCE_SERVER_REQUEST_URI will not automatically decode the Uri for you. This will change in the next major release.

Testing your routes

Since this component has no dependencies, you can create a file as shown below to test your routes:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. // These routes simulate real URIs
  4. $testRoutes = [
  5. '/',
  6. '/index',
  7. '/index/index',
  8. '/index/test',
  9. '/products',
  10. '/products/index/',
  11. '/products/show/101',
  12. ];
  13. $router = new Router();
  14. // Add here your custom routes
  15. // ...
  16. // Testing each route
  17. foreach ($testRoutes as $testRoute) {
  18. // Handle the route
  19. $router->handle($testRoute);
  20. echo 'Testing ', $testRoute, '<br>';
  21. // Check if some route was matched
  22. if ($router->wasMatched()) {
  23. echo 'Controller: ', $router->getControllerName(), '<br>';
  24. echo 'Action: ', $router->getActionName(), '<br>';
  25. } else {
  26. echo "The route wasn't matched by any route<br>";
  27. }
  28. echo '<br>';
  29. }

Events

Like many other components, routers also have events. None of the events can stop the operation. Below is a list of available events

EventDescription
router:beforeCheckRoutesFired before check all loaded routes
router:beforeCheckRouteFired before check a route
router:matchedRouteFired when a route is matched
router:notMatchedRouteFired is any route is matched
router:afterCheckRoutesFired after check all routes
router:beforeMountFired before mount a new route

Annotations Router

This component provides a variant that’s integrated with the annotations service. Using this strategy you can write the routes directly in the controllers instead of adding them in the service registration:

  1. <?php
  2. use Phalcon\Mvc\Router\Annotations as RouterAnnotations;
  3. $di['router'] = function () {
  4. // Use the annotations router. We're passing false as we don't want the router to add its default patterns
  5. $router = new RouterAnnotations(false);
  6. // Read the annotations from ProductsController if the URI starts with /api/products
  7. $router->addResource('Products', '/api/products');
  8. return $router;
  9. };

The annotations can be defined in the following way:

  1. <?php
  2. /**
  3. * @RoutePrefix('/api/products')
  4. */
  5. class ProductsController
  6. {
  7. /**
  8. * @Get(
  9. * '/'
  10. * )
  11. */
  12. public function indexAction()
  13. {
  14. }
  15. /**
  16. * @Get(
  17. * '/edit/{id:[0-9]+}',
  18. * name='edit-robot'
  19. * )
  20. */
  21. public function editAction($id)
  22. {
  23. }
  24. /**
  25. * @Route(
  26. * '/save',
  27. * methods={'POST', 'PUT'},
  28. * name='save-robot'
  29. * )
  30. */
  31. public function saveAction()
  32. {
  33. }
  34. /**
  35. * @Route(
  36. * '/delete/{id:[0-9]+}',
  37. * methods='DELETE',
  38. * conversors={
  39. * id='MyConversors::checkId'
  40. * }
  41. * )
  42. */
  43. public function deleteAction($id)
  44. {
  45. }
  46. public function infoAction($id)
  47. {
  48. }
  49. }

Only methods marked with valid annotations are used as routes. List of annotations supported:

NameDescriptionUsage
RoutePrefixA prefix to be prepended to each route URI. This annotation must be placed at the class’ docblock@RoutePrefix('/api/products')
RouteThis annotation marks a method as a route. This annotation must be placed in a method docblock@Route('/api/products/show')
GetThis annotation marks a method as a route restricting the HTTP method to GET@Get('/api/products/search')
PostThis annotation marks a method as a route restricting the HTTP method to POST@Post('/api/products/save')
PutThis annotation marks a method as a route restricting the HTTP method to PUT@Put('/api/products/save')
DeleteThis annotation marks a method as a route restricting the HTTP method to DELETE@Delete('/api/products/delete/{id}')
OptionsThis annotation marks a method as a route restricting the HTTP method to OPTIONS@Option('/api/products/info')

For annotations that add routes, the following parameters are supported:

NameDescriptionUsage
methodsDefine one or more HTTP method that route must meet with@Route('/api/products', methods={'GET', 'POST'})
nameDefine a name for the route@Route('/api/products', name='get-products')
pathsAn array of paths like the one passed to Phalcon\Mvc\Router::add()@Route('/posts/{id}/{slug}', paths={module='backend'})
conversorsA hash of conversors to be applied to the parameters@Route('/posts/{id}/{slug}', conversors={id='MyConversor::getId'})

If you’re using modules in your application, it is better use the addModuleResource() method:

  1. <?php
  2. use Phalcon\Mvc\Router\Annotations as RouterAnnotations;
  3. $di['router'] = function () {
  4. // Use the annotations router
  5. $router = new RouterAnnotations(false);
  6. // Read the annotations from Backend\Controllers\ProductsController if the URI starts with /api/products
  7. $router->addModuleResource('backend', 'Products', '/api/products');
  8. return $router;
  9. };

Registering Router instance

You can register router during service registration with Phalcon dependency injector to make it available inside the controllers.

You need to add code below in your bootstrap file (for example index.php or app/config/services.php if you use Phalcon Developer Tools.

  1. <?php
  2. /**
  3. * Add routing capabilities
  4. */
  5. $di->set(
  6. 'router',
  7. function () {
  8. require __DIR__ . '/../app/config/routes.php';
  9. return $router;
  10. }
  11. );

You need to create app/config/routes.php and add router initialization code, for example:

  1. <?php
  2. use Phalcon\Mvc\Router;
  3. $router = new Router();
  4. $router->add(
  5. '/login',
  6. [
  7. 'controller' => 'login',
  8. 'action' => 'index',
  9. ]
  10. );
  11. $router->add(
  12. '/products/:action',
  13. [
  14. 'controller' => 'products',
  15. 'action' => 1,
  16. ]
  17. );
  18. return $router;

Implementing your own Router

The Phalcon\Mvc\RouterInterface interface must be implemented to create your own router replacing the one provided by Phalcon.