路由(Routing)

Router 组件允许定义用户请求对应到哪个控制器或动作。Router 解析 URI 以确定这些信息。路由器有两种模式:MVC 模式和匹配模式(match-only)。第一种模式是使用MVC应用程序的理想选择。

定义路由(Defining Routes)

在 MVC 模式中 Phalcon\Mvc\Router 提供了一套简单方便的高级路由功能。你可以自定义路由规则,对应到你需要的 controllers/actions 上。路由的定义如下:

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

add() 方法接受一个匹配模式作为第一个参数,一组可选的路径作为第二个参数。如上,如果URI就是/admin/users/my-profile的话,那么 “users” 控制的 “profile” 方法将被调用。当然路由器并不马上就调用这个方法,它只是收集这些信息并且通知相应的组件(比如 Phalcon\Mvc\Dispatcher )应该调用这个控制器的这个动作。

一个应用程序可以由很多路径,一个一个定义是一个非常笨重的工作。这种情况下我们可以创建一个更加灵活的路由:

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

在上面的例子中我们通过使用通配符定义了一个可以匹配多个URI的路由,比如,访问这个URL(/admin/users/a/delete/dave/301),那么:

|Controller|users
|Action|delete
|Parameter|dave
|Parameter|301

方法 add() 第一个参数,可以使用预定义的占位符和正则表达式的修饰符来作为匹配模式。所有的路由匹配模式第一个字符必须是斜杠(/)。正则表达式的使用跟 PCRE regular expressions 相同。注意,不需要添加正则表达式分隔符,所有路由匹配模式是不区分大小写的。

第二个参数,定义如何将匹配到的数据绑定到对应的 controller/action/parameters。Matchingparts are placeholders or subpatterns delimited by parentheses (round brackets). In the example given above, thefirst subpattern matched (:controller) is the controller part of the route, the second the action and so on.

默认占位符对应正则表达式(Default Placeholders Regular Expressions)

这些占位符帮助编写开发人员更简单的书写正则表达式,而且容易理解,以下默认支持的占位符:

Placeholder Regular Expression Usage
/:module /([\w0-9\_\-]+) Matches a valid module name with alpha-numeric characters only
/:controller /([\w0-9\_\-]+) Matches a valid controller name with alpha-numeric characters only
/:action /([\w0-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 /([\w0-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 characteris 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 indicatetheir relevance, latest routes added have more relevance than first added. Internally, all defined routesare traversed in reverse order until Phalcon\Mvc\Router finds theone that matches the given URI and processes it, while ignoring the rest.

设置占位符对应正则表达式(Setting Placeholders Regular Expressions)

  1. <?php
  2.  
  3. $router = new Phalcon\Mvc\Router(false);
  4.  
  5. // Default
  6. $router->add('/:controller/:action/:params', array(
  7. "controller" => 1,
  8. "action" => 2,
  9. "params" => 3,
  10. ));
  11. // Setting new regular
  12. $router->add('/:controller/:action/:params', array(
  13. "controller" => 1,
  14. "action" => 2,
  15. "params" => 4,
  16. ), array(
  17. '/:controller' => '/([a-zA-Z0-9_-]+)',
  18. '/:action' => '/([a-zA-Z0-9_-]+)',
  19. '/:params' => '([/]?)([a-zA-Z0-9_-]+)?',
  20. ));

参数名称(Parameters with Names)

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

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

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

  1. <?php
  2.  
  3. use Phalcon\Mvc\Controller;
  4.  
  5. class PostsController extends Controller
  6. {
  7. public function indexAction()
  8. {
  9.  
  10. }
  11.  
  12. public function showAction()
  13. {
  14. // Get "year" parameter
  15. $year = $this->dispatcher->getParam("year");
  16. // Or
  17. $year = $this->request->getParam("year");
  18.  
  19. // Get "month" parameter
  20. $month = $this->dispatcher->getParam("month");
  21. // Or
  22. $month = $this->request->getParam("month");
  23.  
  24. // Get "day" parameter
  25. $day = $this->dispatcher->getParam("day");
  26. // Or
  27. $day = $this->request->getParam("day");
  28.  
  29. // ...
  30. }
  31. }

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

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

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

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

短语法(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.  
  3. // Short form
  4. $router->add("/posts/{year:[0-9]+}/{title:[a-z\-]+}", "Posts::show");
  5.  
  6. // Array form
  7. $router->add(
  8. "/posts/([0-9]+)/([a-z\-]+)",
  9. array(
  10. "controller" => "posts",
  11. "action" => "show",
  12. "year" => 1,
  13. "title" => 2
  14. )
  15. );
  16.  
  17. $router = new Phalcon\Mvc\Router;
  18. $router->add('/{namespace:[a-z\-]+}/{controller:[a-z\-]+}{action:[/a-z\-]*}', NULL)
  19. ->convert('namespace', function ($namespace) {
  20. return ucfirst($namespace);
  21. })->convert('controller', function ($controller) {
  22. return ucfirst($controller);
  23. });

混合使用数组和短语法(Mixing Array and Short Syntax)

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

  1. <?php
  2.  
  3. // First position must be skipped because it is used for
  4. // the named parameter 'country'
  5. $router->add('/news/{country:[a-z]{2}}/([a-z+])/([a-z\-+])',
  6. array(
  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.  
  3. use Phalcon\Mvc\Router;
  4.  
  5. $router = new Router(false);
  6.  
  7. $router->add(
  8. '/:module/:controller/:action/:params',
  9. array(
  10. 'module' => 1,
  11. 'controller' => 2,
  12. 'action' => 3,
  13. 'params' => 4
  14. )
  15. );

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

|Module|admin
|Controller|users
|Action|edit
|Parameter|sonny

Or you can bind specific routes to specific modules:

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

Or bind them to specific namespaces:

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

Namespaces/class names must be passed separated:

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

限制 HTTP 请求传入方式(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.  
  3. // This route only will be matched if the HTTP method is GET
  4. $router->addGet("/products/edit/{id}", "Products::edit");
  5.  
  6. // This route only will be matched if the HTTP method is POST
  7. $router->addPost("/products/save", "Products::save");
  8.  
  9. // This route will be matched if the HTTP method is POST or PUT
  10. $router->add("/products/update", "Products::update")->via(array("POST", "PUT"));

使用转换(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.  
  3. // The action name allows dashes, an action can be: /products/new-ipod-nano-4-generation
  4. $router
  5. ->add('/products/{slug:[a-z\-]+}', array(
  6. 'controller' => 'products',
  7. 'action' => 'show'
  8. ))
  9. ->convert('slug', function ($slug) {
  10. // Transform the slug removing the dashes
  11. return str_replace('-', '', $slug);
  12. });

路由分组(Groups of Routes)

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

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

Then mount the group in the router:

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

匹配路由(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 enginemodule. 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.  
  3. use Phalcon\Mvc\Router;
  4.  
  5. // Creating a router
  6. $router = new Router();
  7.  
  8. // Define routes here if any
  9. // ...
  10.  
  11. // Taking URI from $_GET["_url"]
  12. $router->handle();
  13.  
  14. // Or Setting the URI value directly
  15. $router->handle("/employees/edit/17");
  16.  
  17. // Getting the processed controller
  18. echo $router->getControllerName();
  19.  
  20. // Getting the processed action
  21. echo $router->getActionName();
  22.  
  23. // Get the matched route
  24. $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.  
  3. $route = $router->add("/posts/{year}/{title}", "Posts::show");
  4.  
  5. $route->setName("show-posts");
  6.  
  7. // Or just
  8.  
  9. $router->add("/posts/{year}/{title}", "Posts::show")->setName("show-posts");

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

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

范例(Usage Examples)

The following are examples of custom routes:

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

|Controller|documentation
|Action|show
|Parameter|about.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.  
  3. use Phalcon\Mvc\Router;
  4.  
  5. // Create the router without default routes
  6. $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 pagein your website/application:

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

没有找到路径(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.  
  3. // Set 404 paths
  4. $router->notFound(
  5. array(
  6. "controller" => "index",
  7. "action" => "route404"
  8. )
  9. );

This is typically for an Error 404 page.

设置默认路径(Setting default paths)

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

可以为通用路径中的 module, controller, action 定义默认值。当一个路由缺少其中任何一项时,路由器可以自动用默认值填充:

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

处理结尾额外的斜杆(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.  
  3. use Phalcon\Mvc\Router;
  4.  
  5. $router = new Router();
  6.  
  7. // Remove trailing slashes automatically
  8. $router->removeExtraSlashes(true);
  9.  
  10. $router->add('/phalcon', array(
  11. 'controller' => 'index',
  12. 'action' => 'index'
  13. ));

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

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

设置处理结尾额外的斜杆,可以简化路由设置,设置前:

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

设置后:

  1. <?php
  2.  
  3. use Phalcon\Mvc\Router;
  4.  
  5. $router = new Router();
  6. $router->removeExtraSlashes(true);
  7. $router->add('/phalcon', array(
  8. 'controller' => 'index',
  9. 'action' => 'index'
  10. ));

匹配回调函数(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.  
  3. $router->add('/login', array(
  4. 'module' => 'admin',
  5. 'controller' => 'session'
  6. ))->beforeMatch(function ($uri, $route) {
  7. // Check if the request was made with Ajax
  8. if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])
  9. && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
  10. return false;
  11. }
  12. return true;
  13. });

You can re-use these extra conditions in classes:

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

And use this class instead of the anonymous function:

  1. <?php
  2.  
  3. $router->add('/get/info/{id}', array(
  4. 'controller' => 'products',
  5. 'action' => 'info'
  6. ))->beforeMatch(array(new AjaxFilter(), 'check'));

限制主机名(Hostname Constraints)

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

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

The hostname can also be passed as a regular expressions:

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

URI 来源(URI Sources)

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

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

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

  1. <?php
  2.  
  3. $router->handle('/some/route/to/handle');

测试路由(Testing your routes)

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

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

注解路由(Annotations Router)

这个组件利用集成的注解服务 annotations 提供了一个路由定义的变体。通过这个策略,你可以直接在书写控制器的时候编写路由,而不需要一个一个在服务注册的时候添加。

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

注解通过如下的方式定义:

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

只有标记了格式正确的注解的方法才能被用作路由。Phalcon支持如下注解:

名称 描述 用法
RoutePrefix A prefix to be prepended to each route URI. This annotation must be placed at the class’ docblock @RoutePrefix(“/api/products”)
Route This annotation marks a method as a route. This annotation must be placed in a method docblock @Route(“/api/products/show”)
Get This annotation marks a method as a route restricting the HTTP method to GET @Get(“/api/products/search”)
Post This annotation marks a method as a route restricting the HTTP method to POST @Post(“/api/products/save”)
Put This annotation marks a method as a route restricting the HTTP method to PUT @Put(“/api/products/save”)
Delete This annotation marks a method as a route restricting the HTTP method to DELETE @Delete(“/api/products/delete/{id}”)
Options This annotation marks a method as a route restricting the HTTP method to OPTIONS @Option(“/api/products/info”)

用来添加路由的注解支持如下参数:

名称 描述 用法
methods Define one or more HTTP method that route must meet with @Route(“/api/products”, methods={“GET”, “POST”})
name Define a name for the route @Route(“/api/products”, name=”get-products”)
paths An array of paths like the one passed to Phalcon\Mvc\Router::add() @Route(“/posts/{id}/{slug}”, paths={module=”backend”})
conversors A hash of conversors to be applied to the parameters @Route(“/posts/{id}/{slug}”, conversors={id=”MyConversor::getId”})

如果路由对应的控制器属于一个模块,使用 addModuleResource() 效果更佳:

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

设置 URL 生成器(Setting URL Generator)

URL 生成器,帮助 URL 组件生成 URL,例子:

  1. <?php
  2.  
  3. $route = $router->add("/posts/{year}/{title}", "Posts::show");
  4. $route->setName("blog-post")->setUrlGenerator(function($base_uri, $paths, $uri){
  5. return $base_uri.'posts/'.$uri['year'].'-'.$uri['title'].'.html';
  6. });
  7. $url->get(array('for' => 'blog-post', 'title' => 'some-cool-stuff', 'year' => '2012'));

注册路由实例(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. /**
  4. * Add routing capabilities
  5. */
  6. $di->set(
  7. 'router',
  8. function () {
  9. require __DIR__.'/../app/config/routes.php';
  10.  
  11. return $router;
  12. }
  13. );

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

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

REST 模式(REST Mode)

当设置路由为 REST 模式时,会自动将 HTTP method 的值追加到 action 上:

  1. <?php
  2.  
  3. $router = new Phalcon\Mvc\Router();
  4. $router->setMode(Phalcon\Router::MODE_REST);
  5.  
  6. $_SERVER['REQUEST_METHOD'] = 'POST';
  7. $router->handle('/posts/info');
  8.  
  9. echo $router->getActionName(); // 这里将输出 infoPost,如果不开启 REST 模式,将返回 info

自定义路由(Implementing your own Router)

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

原文: http://www.myleftstudio.com/reference/routing.html