路由Routing

路由器组件用来定义处理接收到的请求的路由,指向相应的控制器或者处理程序。路由器只是简单解析一个URI获取这些信息。 路由器有两种模式:MVC模式以及匹配模式。第一种模式主要适合MVC应用。

The router component allows defining 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 提供高级路由支持。在MVC模式下,你可以定义路由并映射向需要的控制器/动作。 一个路由定义方法如下所示:

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. array(
  9. "controller" => "users",
  10. "action" => "profile",
  11. )
  12. );
  13. //Another route
  14. $router->add(
  15. "/admin/users/change-password",
  16. array(
  17. "controller" => "users",
  18. "action" => "changePassword",
  19. )
  20. );
  21. $router->handle();

add()方法接受一个url作为第一个参数,实际执行控制器和方法数组作为第二个参数。路由并不执行任何操作,它只是包含了为组件(例如 Phalcon\Mvc\Dispatcher)提供controller/action的信息集合。

The method add() receives as first parameter a pattern and optionally a set of paths as second parameter. In this case, if the URI is exactly: /admin/users/my-profile, then the “users” controller with its action “profile” will be executed. Currently, the router does not execute the controller and action, it only collects this information to inform the correct component (ie. Phalcon\Mvc\Dispatcher) that this is controller/action it should to execute.

一个应用可能会有很多url路径,一个个去定义非常麻烦。这种情况下我们可以定义一个更加灵活的路由:

An application can have many paths, define 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. array(
  9. "controller" => 1,
  10. "action" => 2,
  11. "params" => 3,
  12. )
  13. );

上面的例子中,使用通配符可以匹配更多的URIs。例如访问(/admin/users/a/delete/dave/301)将会被解析为如下:

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

Controllerusers
Actiondelete
Parameterdave
Parameter301

add()方法可以接受预定义占位符和正则表达式修饰符。所有的路由路径必须由(/)开始。正则表达式语法和 PCRE regular expressions 是一致的。 没有必要添加正则表达式分隔符。所有路由匹配模式是不区分大小写的。

The method add() receives a pattern that optionally could have predefined placeholders and regular expression modifiers. All the routing patterns must start with a 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 routes patterns are case-insensitive.

第二次参数定义了将绑定的参数如何匹配到controller/action/parameters。由括号分隔开的占位符或子模式(圆括号)是匹配部分。在上面的例子中, 第一子模式匹配(:controller)是路由的控制器,第二个动作一次类推。

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

控制器名称采用驼峰命名法。这就意味着(-) 和 (_)将会被移除并且下一个字母将会大写。some_controller将会被转化为SomeController。

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.

因为要使用add()方法添加很多路由规则,添加的顺序决定了它们匹配的顺序,最后添加路由规格优于最先添加的。在内部所有定义的规格都是按照相反顺序执行的,直到 Phalcon\Mvc\Router 匹配到一个URI规格并执行,后面的规则将会被忽略。

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.

参数名称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. array(
  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. );

在上面的例子中,路由没有定义controller和action。它们被posts和show固定替换了。用户觉察不到已经使用了默认路由。在控制器内部可以使用如下方式获得参数。

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. // Return "year" parameter
  11. $year = $this->dispatcher->getParam("year");
  12. // Return "month" parameter
  13. $month = $this->dispatcher->getParam("month");
  14. // Return "day" parameter
  15. $day = $this->dispatcher->getParam("day");
  16. }
  17. }

注意参数值是从分配器中获得的。之所以可以这样是因为它是最后与驱动应用程序交互的组件。此外,还有另外一个方法来创建命名参数:

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. array(
  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. // Returns "name" parameter
  8. $name = $this->dispatcher->getParam("name");
  9. // Returns "type" parameter
  10. $type = $this->dispatcher->getParam("type");
  11. }
  12. }

短语法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("/posts/{year:[0-9]+}/{title:[a-z\-]+}", "Posts::show");
  4. // Array form
  5. $router->add(
  6. "/posts/([0-9]+)/([a-z\-]+)",
  7. array(
  8. "controller" => "posts",
  9. "action" => "show",
  10. "year" => 1,
  11. "title" => 2,
  12. )
  13. );

数组和短语法混合使用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('/news/{country:[a-z]{2}}/([a-z+])/([a-z\-+])',
  5. array(
  6. 'section' => 2, //Positions start with 2
  7. 'article' => 3
  8. )
  9. );

路由到模块Routing to Modules

可以定义路径中包含模块的路由。这适用于多模块的应用。可以定义一个包含module通配符的默认路由:

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('/:module/:controller/:action/:params', array(
  5. 'module' => 1,
  6. 'controller' => 2,
  7. 'action' => 3,
  8. 'params' => 4
  9. ));

在这种情况下路由中必须包含模块名。如下所示,URL: /admin/users/edit/sonny将会被解析为:

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:

Moduleadmin
Controllerusers
Actionedit
Parametersonny

或者可以绑定特定的模块到路由中:

Or you can bind specific routes to specific modules:

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

或者是绑定到特定的命名空间:

Or bind them to specific namespaces:

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

Namespaces/class必须被单独传递:

Namespaces/class names must be passed separated:

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

限制 HTTP 请求传入方式 HTTP Method Restrictions

使用add()添加路由方法后,会被应用到所有的http方法。我们可以限制路由到特定的方法中,在创建RESTful应用的时候非常有用:

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("/products/edit/{id}", "Products::edit");
  4. // This route only will be matched if the HTTP method is POST
  5. $router->addPost("/products/save", "Products::save");
  6. // This route will be matched if the HTTP method is POST or PUT
  7. $router->add("/products/update")->via(array("POST", "PUT"));

使用转换Using convertions

在将请求传递给分配器前转换方法可以将路由参数进行灵活的转换。下面示例演示如何使用:

Convertions allow 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. $router
  4. ->add('/products/{slug:[a-z\-]+}', array(
  5. 'controller' => 'products',
  6. 'action' => 'show'
  7. ))
  8. ->convert('slug', function($slug) {
  9. //Transform the slug removing the dashes
  10. return str_replace('-', '', $slug);
  11. });

路由分组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(array(
  7. 'module' => 'blog',
  8. 'controller' => 'index'
  9. ));
  10. //All the routes start with /blog
  11. $blog->setPrefix('/blog');
  12. //Add a route to the group
  13. $blog->add('/save', array(
  14. 'action' => 'save'
  15. ));
  16. //Add another route to the group
  17. $blog->add('/edit/{id}', array(
  18. 'action' => 'edit'
  19. ));
  20. //This route maps to a controller different than the default
  21. $blog->add('/blog', array(
  22. 'controller' => 'blog',
  23. 'action' => 'index'
  24. ));
  25. //Add the group to the router
  26. $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(array(
  9. 'module' => 'blog',
  10. 'namespace' => 'Blog\Controllers'
  11. ));
  12. //All the routes start with /blog
  13. $this->setPrefix('/blog');
  14. //Add a route to the group
  15. $this->add('/save', array(
  16. 'action' => 'save'
  17. ));
  18. //Add another route to the group
  19. $this->add('/edit/{id}', array(
  20. 'action' => 'edit'
  21. ));
  22. //This route maps to a controller different than the default
  23. $this->add('/blog', array(
  24. 'controller' => 'blog',
  25. 'action' => 'index'
  26. ));
  27. }
  28. }

然后在路由中加载路由分组:

Then mount the group in the router:

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

匹配路由Matching Routes

需要传递给路由正确的URI。默认情况下从重写引擎模块的$_GET[‘_url’] 变量中取得路由URI,可以对phalcon应用一些的正则重写:

A valid URI must be passed to Router in order to let it checks the route that matches that given URI. 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 ^(.*)$ index.php?_url=/$1 [QSA,L]

下面的例子演示了如何独立使用路由组件:

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

添加到路由器中的路由会被当做对象储存在:doc:`Phalcon\Mvc\Router\Route <../api/Phalcon_Mvc_Router_Route>`中。它封装了路由的细节。在应用中我们可以给路径一个特定的名称。当我们从路由中创建连接的时候非常有用。

Each route that is added to the router is stored internally as an object Phalcon\Mvc\Router\Route. 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("/posts/{year}/{title}", "Posts::show");
  3. $route->setName("show-posts");
  4. //or just
  5. $router->add("/posts/{year}/{title}", "Posts::show")->setName("show-posts");

使用:doc:`Phalcon\Mvc\Url <../api/Phalcon_Mvc_Url>`可以从名称创建路由连接:

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(array(
  4. "for" => "show-posts",
  5. "year" => "2012",
  6. "title" => "phalcon-1-0-released"
  7. ));

范例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. array(
  6. "controller" => 1,
  7. "action" => 2,
  8. "params" => 3
  9. )
  10. );
  11. // matches "/es/news"
  12. $router->add(
  13. "/([a-z]{2})/:controller",
  14. array(
  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. array(
  24. "controller" => 2,
  25. "action" => "index"
  26. )
  27. );
  28. // matches "/admin/posts/edit/100"
  29. $router->add(
  30. "/admin/:controller/:action/:int",
  31. array(
  32. "controller" => 1,
  33. "action" => 2,
  34. "id" => 3
  35. )
  36. );
  37. // matches "/posts/2010/02/some-cool-content"
  38. $router->add(
  39. "/posts/([0-9]{4})/([0-9]{2})/([a-z\-]+)",
  40. array(
  41. "controller" => "posts",
  42. "action" => "show",
  43. "year" => 1,
  44. "month" => 2,
  45. "title" => 4
  46. )
  47. );
  48. // matches "/manual/en/translate.adapter.html"
  49. $router->add(
  50. "/manual/([a-z]{2})/([a-z\.]+)\.html",
  51. array(
  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('/api/(v1|v2)/{method:[a-z]+}/{param:[a-z]+}\.(json|xml)',
  65. array(
  66. 'controller' => 'api',
  67. 'version' => 1,
  68. 'format' => 4
  69. )
  70. );

注意在控制器和命名空间使用的字符,这些字符会被转换为类名并传递给文件系统,可能会让攻击者读取未授权文件。安全的正则表达式为/([a-zA-Z0-9_-]+)。

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

:doc:`Phalcon\Mvc\Router <../api/Phalcon_Mvc_Router>`有默认的路由行为。匹配如下格式/:controller/:action/:params

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

例如, *http://phalconphp.com/documentation/show/about.html*链接会被解析为如下格式:

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

Controllerdocumentation
Actionshow
Parameterabout.html

如果不想使用默认路由规格在应用中,可以在创建的时候传入false值:

If you don’t want use this routes as default in your application, you must create the router passing false as 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("/", array(
  3. 'controller' => 'index',
  4. 'action' => 'index'
  5. ));

没有找到路径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(array(
  4. "controller" => "index",
  5. "action" => "route404"
  6. ));

设置默认路径Setting default paths

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

It’s possible to define default values for common paths like 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(array(
  9. 'controller' => 'index',
  10. 'action' => 'index'
  11. ));

处理结尾额外的斜杆Dealing with extra/trailing slashes

Sometimes a route could be accessed with extra/trailing slashes and the end of the route, 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. $router->add(
  3. '/{language:[a-z]{2}}/:controller[/]{0,1}',
  4. array(
  5. 'controller' => 2,
  6. 'action' => 'index'
  7. )
  8. );

匹配回调函数Match Callbacks

有时在特定条件下路由必须被匹配,可以使用beforeMatch回调函数添加任意的条件。如果函数返回false,路由匹配失败:

Sometimes, routes must 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 treaded as non-matched:

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

类中定义可以重用代码:

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. $router->add('/get/info/{id}', array(
  3. 'controller' => 'products',
  4. 'action' => 'info'
  5. ))->beforeMatch(array(new AjaxFilter(), 'check'));

限制主机名Hostname Constraints

路由可以设置限制主机名,只有匹配主机名的才能应用特定的路由或者是路由群组:

The router allow 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. $router->add('/login', array(
  3. 'module' => 'admin',
  4. 'controller' => 'session',
  5. 'action' => 'login'
  6. ))->setHostName('admin.company.com');

主机名也可以是正则表达式:

Hostname can also be regular expressions:

  1. <?php
  2. $router->add('/login', array(
  3. 'module' => 'admin',
  4. 'controller' => 'session',
  5. 'action' => 'login'
  6. ))->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(array(
  5. 'module' => 'blog',
  6. 'controller' => 'posts'
  7. ));
  8. //Hostname restriction
  9. $blog->setHostName('blog.mycompany.com');
  10. //All the routes start with /blog
  11. $blog->setPrefix('/blog');
  12. //Default route
  13. $blog->add('/', array(
  14. 'action' => 'index'
  15. ));
  16. //Add a route to the group
  17. $blog->add('/save', array(
  18. 'action' => 'save'
  19. ));
  20. //Add another route to the group
  21. $blog->add('/edit/{id}', array(
  22. 'action' => 'edit'
  23. ));
  24. //Add the group to the router
  25. $router->mount($blog);

URI 来源 URI Sources

默认情况下URI信息从$_GET[‘_url’]变量中获得,它由重新引擎传递给phalcon,如果需要可以直接使用$_SERVER[‘REQUEST_URI’]。

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. $router->setUriSource(Router::URI_SOURCE_GET_URL); // use $_GET['_url'] (default)
  5. $router->setUriSource(Router::URI_SOURCE_SERVER_REQUEST_URI); // use $_SERVER['REQUEST_URI'] (default)

或者手动传递URI给handle方法:

Or you can manually pass a URI to the ‘handle’ method:

  1. <?php
  2. $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. use Phalcon\Mvc\Router;
  3. //These routes simulate real URIs
  4. $testRoutes = array(
  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. }

路由注解 Annotations Router

路由组件有一个和:doc:`annotations <annotations>`注解组件高度整合的变体。使用它我们可以在控制器中直接定义路由而不用再在注册服务中去定义了。

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
  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. public function indexAction()
  11. {
  12. }
  13. /**
  14. * @Get("/edit/{id:[0-9]+}", name="edit-robot")
  15. */
  16. public function editAction($id)
  17. {
  18. }
  19. /**
  20. * @Route("/save", methods={"POST", "PUT"}, name="save-robot")
  21. */
  22. public function saveAction()
  23. {
  24. }
  25. /**
  26. * @Route("/delete/{id:[0-9]+}", methods="DELETE",
  27. * conversors={id="MyConversors::checkId"})
  28. */
  29. public function deleteAction($id)
  30. {
  31. }
  32. public function infoAction($id)
  33. {
  34. }
  35. }

只有方法被标注了有效的注解才能被作为路由。支持的注解如下:

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”})

如果在模块中要映射路由到控制器最好使用addModuleResource方法:

If routes map to controllers in modules 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

可以在服务注册的时候使用Phalcon的依赖注入完成路由器注册从而保证在控制器中全部可用。需要在启动代码里添加如下代码。(例如在/index.php或者使用`Phalcon Developer Tools <http://phalconphp.com/en/download/tools>`_ 添加至app/config/services.php )

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

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('router', function(){
  6. require __DIR__.'/../app/config/routes.php';
  7. return $router;
  8. });

需要创建app/config/routes.php并添加路由器初始化代码,例如:

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("/login", array(
  5. 'controller' => 'login',
  6. 'action' => 'index',
  7. ));
  8. $router->add("/products/:action", array(
  9. 'controller' => 'products',
  10. 'action' => 1,
  11. ));
  12. return $router;

实现自定义路由Implementing your own Router

Phalcon\Mvc\RouterInterface 在创建自定义路由的时候必须先被集成实现。

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