路由器(Routing) ============================= router组件å…许定义用户请求对应到哪个控制器或Action。routerè§£æž URI 以确定这些信æ¯ã€‚è·¯ç”±å™¨æœ‰ä¸¤ç§æ¨¡å¼ï¼šMVC模å¼å’ŒåŒ¹é…模å¼(match-only)ã€‚ç¬¬ä¸€ç§æ¨¡å¼æ˜¯ä½¿ç”¨MVC应用程åºçš„ç†æƒ³é€‰æ‹©ã€‚ Defining Routes --------------- :doc:`Phalcon\\Mvc\\Router <../api/Phalcon_Mvc_Router>` æä¾›äº†ä¸€å¥—先进的路由功能。在MVC模å¼ä¸ï¼Œä½ å¯ä»¥è‡ªå®šä¹‰è·¯ç”±è§„åˆ™ï¼Œå¯¹åº”åˆ°ä½ éœ€è¦çš„ controllers/actions 上。路由的定义如下: .. code-block:: php <?php // Create the router $router = new \Phalcon\Mvc\Router(); //Define a route $router->add( "/admin/users/my-profile", array( "controller" => "users", "action" => "profile", ) ); //Another route $router->add( "/admin/users/change-password", array( "controller" => "users", "action" => "changePassword", ) ); $router->handle(); add() æ–¹æ³•æŽ¥æ”¶ä¸¤ä¸ªå‚æ•°ï¼Œç¬¬ä¸€ä¸ªå‚数是一个匹é…å—ç¬¦ä¸²ï¼Œç¬¬äºŒä¸ªå‚æ•°ä¸ºä¸€ç»„å¯é€‰çš„è·¯å¾„ã€‚åœ¨è¿™ç§æƒ…况下,URI /admin/users/my-profile, "users"代表控制器,"profile"代表Ation。目å‰ï¼Œè¯¥è·¯ç”±å™¨ä¸å¹¶ä¸æ‰§è¡ŒæŽ§åˆ¶å™¨å’ŒAction,åªä¸ºç»„ä»¶(如: :doc:`Phalcon\\Mvc\\Dispatcher <../api/Phalcon_Mvc_Dispatcher>`) 收集信æ¯ï¼Œç„¶åŽç”±åˆ†å‘器决定是å¦ç«‹å³æ‰§è¡Œã€‚ 应用程åºå¯èƒ½æœ‰å¾ˆå¤šä¸ªä¸åŒçš„路径,如果一个一个的定义路由的è¯ï¼Œä¼šéžå¸¸éº»çƒ¦ã€‚åœ¨è¿™ç§æƒ…况下,我们å¯ä»¥ä½¿ç”¨æ›´çµæ´»çš„æ–¹å¼åˆ›å»ºroute: .. code-block:: php <?php // Create the router $router = new \Phalcon\Mvc\Router(); //Define a route $router->add( "/admin/:controller/a/:action/:params", array( "controller" => 1, "action" => 2, "params" => 3, ) ); 在上é¢çš„例åä¸ï¼Œæˆ‘们使用通é…符æ¥åŒ¹é…路由。例如,通过访问URL (/admin/users/a/delete/dave/301) ,解æžä¸ºï¼š +------------+---------------+ | Controller | users | +------------+---------------+ | Action | delete | +------------+---------------+ | Parameter | dave | +------------+---------------+ | Parameter | 301 | +------------+---------------+ add()方法接收一个模å¼ï¼Œå¯é€‰æ‹©ä½¿ç”¨é¢„定义å ä½ç¬¦å’Œæ£åˆ™è¡¨è¾¾å¼ä¿®é¥°ç¬¦ã€‚所有的路由模å¼å¿…须以斜线å—符(/)开始。æ£åˆ™è¡¨è¾¾å¼è¯æ³•使用与 `PCRE regular expressions`_ 相åŒçš„è¯æ³•ã€‚éœ€è¦æ³¨æ„的是,ä¸å¿…è¦æ·»åŠ æ£åˆ™è¡¨è¾¾å¼åˆ†éš”ç¬¦ã€‚æ‰€æœ‰çš„è·¯ç”±æ¨¡å¼æ˜¯ä¸åŒºåˆ†å¤§å°å†™çš„。 ç¬¬äºŒä¸ªå‚æ•°å®šä¹‰äº†å¦‚何将匹é…部分绑定到controller/action/parameters。匹é…部分是å ä½ç¬¦æˆ–团圆括å·ä¸çš„忍¡å¼ã€‚å¦å¤–,在上述的例åä¸ï¼Œç¬¬ä¸€ä¸ªå模å¼åŒ¹é…(:controller),是routeä¸æŽ§åˆ¶å™¨éƒ¨åˆ†ï¼Œç¬¬äºŒä¸ªæ˜¯action,ç‰ã€‚ 这些å ä½ç¬¦ä½¿ç”¨æ£åˆ™è¡¨è¾¾å¼ï¼Œæ›´æ˜“读,更容易为开å‘人员ç†è§£ã€‚支æŒä»¥ä¸‹å ä½ç¬¦ï¼š +--------------+---------------------+--------------------------------------------------------------------+ | Placeholder | Regular Expression | Usage | +==============+=====================+====================================================================+ | /: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 | +--------------+---------------------+--------------------------------------------------------------------+ | /:namespace | /([a-zA-Z0-9\_\-]+) | Matches a single level namespace name | +--------------+---------------------+--------------------------------------------------------------------+ | /:int | /([0-9]+) | Matches an integer parameter | +--------------+---------------------+--------------------------------------------------------------------+ 控制器å称采用驼峰书写规则,这æ„味ç€ï¼Œå—符 (-) å’Œ (_)å°†è¢«ç§»é™¤ï¼ŒåŒæ—¶æŠŠä¸‹ä¸€ä¸ªå—符转化为大写å—符。比如,some_controller被转化为SomeController。 Since you can add many routes as you need using add(), the order in which you add the routes indicates their relevance, last routes added have more relevance than first added. Internally, all defined routes are traversed in reverse order until :doc:`Phalcon\\Mvc\\Router <../api/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: .. code-block:: php <?php $router->add( "/news/([0-9]{4})/([0-9]{2})/([0-9]{2})/:params", array( "controller" => "posts", "action" => "show", "year" => 1, // ([0-9]{4}) "month" => 2, // ([0-9]{2}) "day" => 3, // ([0-9]{2}) "params" => 4, // :params ) ); 在上述的例åä¸ï¼Œè¯¥è·¯ç”±å¹¶æ²¡æœ‰å®šä¹‰"controller" å’Œ "action"部分。这两部分被固定值("posts" å’Œ "show")å–代。用户并ä¸çŸ¥é“使用的是哪个控制器。在控制器内部,å¯ä»¥é€šè¿‡ä»¥ä¸‹æ–¹å¼è®¿é—®è¿™äº›å‚数: .. code-block:: php <?php class PostsController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function showAction() { // Return "year" parameter $year = $this->dispatcher->getParam("year"); // Return "month" parameter $month = $this->dispatcher->getParam("month"); // Return "day" parameter $day = $this->dispatcher->getParam("day"); } } 请注æ„,上述示例ä¸ä¼ é€’çš„å‚æ•°æ˜¯ä½¿ç”¨dispatcher获å–的。æ¤å¤–,也有å¦ä¸€ç§æ–¹æ³•æ¥åˆ›å»ºå‘½å傿•°ä½œä¸ºæ¨¡å¼çš„一部分: .. code-block:: php <?php $router->add( "/documentation/{chapter}/{name}.{type:[a-z]+}", array( "controller" => "documentation", "action" => "show" ) ); ä½ å¯ä»¥æŒ‰ä¸Šé¢çš„例åä¸€æ ·çš„æ–¹å¼èŽ·å–他们的值: .. code-block:: php <?php class DocumentationController extends \Phalcon\Mvc\Controller { public function showAction() { // Returns "name" parameter $year = $this->dispatcher->getParam("name"); // Returns "type" parameter $year = $this->dispatcher->getParam("type"); } } Short Syntax ^^^^^^^^^^^^ å¦‚æžœä½ ä¸å–œæ¬¢ä½¿ç”¨ä¸€ä¸ªæ•°ç»„çš„å½¢å¼æ¥å®šä¹‰è·¯ç”±ï¼Œå¯ä»¥ä½¿ç”¨å¦ä¸€ç§è¯æ³•。下é¢çš„示例产生相åŒçš„结果: .. code-block:: php <?php // Short form $router->add("/posts/{year:[0-9]+}/{title:[a-z\-]+}", "Posts::show"); // Array form: $router->add( "/posts/([0-9]+)/([a-z\-]+)", array( "controller" => "posts", "action" => "show", "year" => 1, "title" => 2, ) ); 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: .. code-block:: php <?php //First position must be skipped because it is used for //the named parameter 'country' $router->add('/news/{country:[a-z]{2}}/([a-z+])/([a-z\-+])', array( 'section' => 2, //Positions start with 2 'article' => 3 ) ); Routing to Modules ^^^^^^^^^^^^^^^^^^ ä½ å¯ä»¥åœ¨è·¯ç”±å®šä¹‰ä¸åŒ…å«module,这适åˆå¤šä¸ªmodule的应用程åºã€‚定义路由也å¯ä»¥ä½¿ç”¨ç¼ºçœè®¾ç½®ï¼š .. code-block:: php <?php $router = new Phalcon\Mvc\Router(false); $router->add('/:module/:controller/:action/:params', array( 'module' => 1, 'controller' => 2, 'action' => 3, 'params' => 4 )); åœ¨è¿™ç§æƒ…况下,URL部分必须包å«moduleçš„å称。例如,下é¢çš„URL:/admin/users/edit/sonny,将被解æžä¸ºï¼š +------------+---------------+ | Module | admin | +------------+---------------+ | Controller | users | +------------+---------------+ | Action | edit | +------------+---------------+ | Parameter | sonny | +------------+---------------+ æˆ–è€…ï¼Œä½ ä¹Ÿå¯ä»¥ç»‘定特定的module到路由上: .. code-block:: php <?php $router->add("/login", array( 'module' => 'backend', 'controller' => 'login', 'action' => 'index', )); $router->add("/products/:action", array( 'module' => 'frontend', 'controller' => 'products', 'action' => 1, )); 也å¯ç»‘定到特定的命å空间上: .. code-block:: php <?php $router->add("/:namespace/login", array( 'namespace' => 1, 'controller' => 'login', 'action' => 'index' )); controllerä¹Ÿå¯æŒ‡å®šå…¨ç§°ï¼š .. code-block:: php <?php $router->add("/login", array( 'controller' => 'Backend\Controllers\Login', 'action' => 'index' )); HTTP Method Restrictions ^^^^^^^^^^^^^^^^^^^^^^^^ å½“ä½ ä½¿ç”¨add()æ–¹æ³•æ·»åŠ ä¸€ä¸ªè·¯ç”±æ—¶ï¼Œè¯¥è·¯ç”±å°†åº”ç”¨åˆ°æ‰€æœ‰HTTP方法上。有时候,我们想è¦é™åˆ¶åˆ°ä¸€ä¸ªç‰¹å®šçš„HTTP方法,比如创建一个RESTfulçš„åº”ç”¨ç¨‹åºæ—¶ï¼š .. code-block:: php <?php // This route only will be matched if the HTTP method is GET $router->addGet("/products/edit/{id}", "Posts::edit"); // This route only will be matched if the HTTP method is POST $router->addPost("/products/save", "Posts::save"); // This route will be matched if the HTTP method is POST or PUT $router->add("/products/update")->via(array("POST", "PUT")); Matching Routes --------------- 现在,我们需è¦å®šä¹‰ä¸€ä¸ªè·¯ç”±ï¼Œä»¥æ£€æŸ¥å®šä¹‰çš„路由是å¦åŒ¹é…给定的URL。默认情况下,路由的URIå¯ä»¥é€šè¿‡ $_GET['url'] 这个å˜é‡èŽ·å¾—ï¼ŒPhalconå¯ä»¥ä½¿ç”¨ä¸‹åˆ—URLé‡å†™è§„则很好的工作: .. code-block:: apacheconf RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] 下é¢çš„示例将展示如果使用æ¤ç»„件: .. code-block:: php <?php // Creating a router $router = new \Phalcon\Mvc\Router(); // Define routes here if any // ... // Taking URI from $_GET["_url"] $router->handle(); // or Setting the URI value directly $router->handle("/employees/edit/17"); // Getting the processed controller echo $router->getControllerName(); // Getting the processed action echo $router->getActionName(); //Get the matched route $route = $router->getMatchedRoute(); Naming Routes ------------- æ¯ä¸ªè¢«æ·»åŠ çš„è·¯ç”±éƒ½å˜å‚¨åˆ°å¯¹è±¡ :doc:`Phalcon\\Mvc\\Router\\Route <../api/Phalcon_Mvc_Router_Route>` ä¸ï¼Œè¿™ä¸ªç±»å°è£…了路由的细节。例如,我们å¯ä»¥ç»™åº”用程åºä¸çš„路由设置一个唯一的åç§°ã€‚å¦‚æžœä½ æƒ³åˆ›å»ºURLs,这将éžå¸¸æœ‰ç”¨ã€‚ .. code-block:: php <?php $route = $router->add("/posts/{year}/{title}", "Posts::show"); $route->setName("show-posts"); //or just $router->add("/posts/{year}/{title}", "Posts::show")->setName("show-posts"); ç„¶åŽï¼Œæˆ‘们å¯ä»¥ä½¿ç”¨ :doc:`Phalcon\\Mvc\\Url <../api/Phalcon_Mvc_Url>` 组件通过路由的å称创建一个路由: .. code-block:: php <?php // returns /posts/2012/phalcon-1-0-released $url->get(array("for" => "show-posts", "year" => "2012", "title" => "phalcon-1-0-released")); 用法示例 -------------- 䏋颿˜¯è‡ªå®šä¹‰è·¯ç”±çš„例å: .. code-block:: php <?php // matches "/system/admin/a/edit/7001" $router->add( "/system/:controller/a/:action/:params", array( "controller" => 1, "action" => 2, "params" => 3, ) ); // matches "/es/news" $router->add( "/([a-z]{2})/:controller", array( "controller" => 2, "action" => "index", "language" => 1, ) ); // matches "/es/news" $router->add( "/{language:[a-z]{2}}/:controller", array( "controller" => 2, "action" => "index", ) ); // matches "/admin/posts/edit/100" $router->add( "/admin/:controller/:action/:int", array( "controller" => 1, "action" => 2, "id" => 3, ) ); // matches "/posts/2010/02/some-cool-content" $router->add( "/posts/([0-9]{4})/([0-9]{2})/([a-z\-]+)", array( "controller" => "posts", "action" => "show", "year" => 1, "month" => 2, "title" => 4, ) ); // matches "/manual/en/translate.adapter.html" $router->add( "/manual/([a-z]{2})/([a-z\.]+)\.html", array( "controller" => "manual", "action" => "show", "language" => 1, "file" => 2, ) ); // matches /feed/fr/le-robots-hot-news.atom $router->add( "/feed/{lang:[a-z]+}/{blog:[a-z\-]+}\.{type:[a-z\-]+}", "Feed::get" ); .. highlights:: 请注æ„ï¼Œå› ä¸ºæŽ§åˆ¶å™¨å’Œå‘½å空间å…许使用æ£è§„表达å¼ï¼Œå› æ¤ï¼Œä¸€äº›æ”»å‡»éƒ½å¯èƒ½ä¼šåè¿‡æ¥æŽ¨å¯¼å‡ºæ–‡ä»¶ç³»ç»Ÿä¸æœªç»æŽˆæƒçš„æ–‡ä»¶ã€‚一个安全的æ£åˆ™è¡¨è¾¾å¼ï¼š /([a-zA-Z0-9\_\-]+) Default Behavior ---------------- :doc:`Phalcon\\Mvc\\Router <../api/Phalcon_Mvc_Router>` 有一个默认æä¾›äº†ä¸€ä¸ªéžå¸¸ç®€å•的路由,总是匹é…è¿™æ ·çš„æ¨¡å¼ï¼š/:controller/:action/:params 。 例如,对于URL *http://phalconphp.com/documentation/show/about.html* ,路由将按如下方å¼è§£æžï¼š +------------+---------------+ | Controller | documentation | +------------+---------------+ | Action | show | +------------+---------------+ | Parameter | about.html | +------------+---------------+ å¦‚æžœä½ ä¸æƒ³åœ¨åº”用程åºä¸ä½¿ç”¨è·¯ç”±çš„é»˜è®¤è¡Œä¸ºï¼Œä½ å¯ä»¥åˆ›å»ºä¸€ä¸ªè·¯ç”±ï¼Œå¹¶æŠŠfalse傿•°ä¼ 递给它: .. code-block:: php <?php // Create the router without default routes $router = new \Phalcon\Mvc\Router(false); Setting default paths --------------------- ä½ å¯ä»¥å¯¹module,controller,actionè®¾ç½®é»˜è®¤å€¼ï¼Œå½“åœ¨è·¯ç”±ä¸æ‰¾ä¸åˆ°è·¯å¾„时,它将自动填充它: .. code-block:: php <?php //Individually $router->setDefaultController("index"); $router->setDefaultAction("index"); //Using an array $router->setDefaults(array( "controller" => "index", "action" => "index" )); 译者注:比如一个å•module的站点,URL:http://site/ï¼Œå…¶ä¸æ²¡æœ‰controllerå’Œaction,那么默认它将访问 http://site/index/index Testing your routes ------------------- 由于æ¤ç»„ä»¶ä¸å˜åœ¨ä¾èµ–å…³ç³»ï¼Œä½ å¯ä»¥åˆ›å»ºä¸€ä¸ªæ–‡ä»¶æ¥æµ‹è¯•ä½ çš„è·¯ç”±ï¼Œå¦‚ä¸‹æ‰€ç¤ºï¼š .. code-block:: php <?php //These routes simulate real URIs $testRoutes = array( '/', '/index', '/index/index', '/index/test', '/products', '/products/index/', '/products/show/101', ); $router = new Phalcon\Mvc\Router(); //Add here your custom routes //Testing each route foreach ($testRoutes as $testRoute) { //Handle the route $router->handle($testRoute); echo 'Testing ', $testRoute, '<br>'; //Check if some route was matched if ($router->wasMatched()) { echo 'Controller: ', $router->getControllerName(), '<br>'; echo 'Action: ', $router->getActionName(), '<br>'; } else { echo 'The route wasn\'t matched by any route<br>'; } echo '<br>'; } Implementing your own Router ---------------------------- Phalcon 还æä¾›äº† :doc:`Phalcon\\Mvc\\RouterInterface <../api/Phalcon_Mvc_RouterInterface>` 接å£ç”¨æ¥å®žçŽ°è‡ªå®šä¹‰è·¯ç”±ã€‚ .. _PCRE regular expressions: http://www.php.net/manual/en/book.pcre.php