Zend_Controller_Router_Rewrite是標准的框架路由器。路由是個過程,在這個過程中它取出URI的端點(跟著基本URL的URI的那部分)並把它分解成參數來決定哪個模塊、哪個控制器和控制器中的哪個動作應該接受請求。模塊、控制器、動作和其它參數被打包到Zend_Controller_Request_Http對象,接著這個對象由Zend_Controller_Dispatcher_Standard來處理。路由只發生一次:當請求最初被接收和第一個控制器被派遣之前。
Zend_Controller_Router_Rewrite被設計來考慮使用純php結構時mod_rewrite-like的功能性。它非常寬松地基於Ruby on Rails並且不要求任何先前的web服務器URL rewriting的知識。它被設計來和單個Apache的 mod_rewrite規則(其中之一)一起工作:
RewriteEngine on RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
或者:
RewriteEngine on RewriteCond %{SCRIPT_FILENAME} !-f RewriteCond %{SCRIPT_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1
為正確使用rewrite路由器你必須初始化它,添加一些用戶定義的路由並注入到控制器。下面的代碼示例這個過程:
<?php /* Create a router */ $router = $ctrl->getRouter(); // returns a rewrite router by default $router->addRoute( 'user', new Zend_Controller_Router_Route('user/:username', array('controller' => 'user', 'action' => 'info')) );
RewriteRouter的核心是用戶定義路由的定義。路由通過調用RewriteRouter的addRoute方法和傳遞一個由類實現的Zend_Controller_Router_Route_Interface的新的實例被添加。例如:
<?php $router->addRoute('user', new Zend_Controller_Router_Route('user/:username'));
Rewrite 路由器帶有四個基本類型的路由(其中一個是特殊的):
路由可以被使用無數次來創建鏈或用戶定義的應用程序路由計劃。你可以在任何配置中使用任何數量的路由,除了模塊路由以外,它最好被用一次並作為通用路由(例如,作為缺省的)。每個路由將在稍後詳細描述。
addRoute的第一個參數是路由名。它用來作為權柄從路由器中取得路由(例如,for URL generation purposes)。第二個參數是路由自己。路由名最普通的用法是通過Zend_View_url助手的方法:
<a href="<?= $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
路由是一個簡單的過程,這個過程通過所有提供的路由和匹配它的當前請求的URI定義來迭代。當一個正匹配被發現,變量值從路由實例返回並注入到Zend_Controller_Request對象以備將來在派遣器和用戶創建的控制器中使用。如果是負匹配,在鏈中的下個路由被檢查。從路由返回的值來自於URL參數或用於定義的缺省值。這些變量以後可通過Zend_Controller_Request::getParam() 或 Zend_Controller_Action::_getParam() 方法來訪問。
有三個特殊的變量可用於你的路由-'module'、 'controller' 和 'action'。這些特殊的變量被Zend_Controller_Dispatcher用來找出控制器和動作然後派遣過去。
Zend_Controller_Router_Rewrite 和缺省路由一起預先配置,它將以controller/action的形式匹配URIs。另外,模塊名可以被指定作為第一個路徑參數,允許這種module/controller/action形式的URIs。最後,它也將缺省地匹配任何另外的追加到URI的參數-controller/action/var1/value1/var2/value2。
一些路由如何匹配的例子:
// Assuming the following: $ctrl->setControllerDirectory( array( 'default' => '/path/to/default/controllers', 'news' => '/path/to/news/controllers', 'blog' => '/path/to/blog/controllers' ) ); Module only: http://example/news module == news Invalid module maps to controller name: http://example/foo controller == foo Module + controller: http://example/blog/archive module == blog controller == archive Module + controller + action: http://example/blog/archive/list module == blog controller == archive action == list Module + controller + action + params: http://example/blog/archive/list/sort/alpha/date/desc module == blog controller == archive action == list sort == alpha date == desc
缺省路由是存儲在RewriteRouter名(index)為'default'的簡單的Zend_Controller_Router_Route_Module對象。它被創建多多少少象下面這樣:
<?php $compat = new Zend_Controller_Router_Route_Module(array(), $dispatcher, $request); $this->addRoute('default', $compat);
如果你不想這個特別的缺省路由在你的路由計劃中,你可以重寫你自己的'缺省'路由(例如,把它存儲在'default'名下)或用removeDefaultRoutes()完全清除它:
<?php // Remove any default routes $router->removeDefaultRoutes();
Zend_Controller_Router_Route 是標准的框架路由。它結合了靈活路由定義的易用性。每個路由包含了基本的URL映射(靜態的和動態的部分(變量))並且可以被缺省地初始化,也可以根據不同的要求初始化。
讓我們想象一下我們假設的應用程序將需要一些廣域內容作者的信息頁面。我們想能夠把浏覽器指向http://domain.com/author/martel去看一個叫"martel"的信息。有這樣功能的路由看起來是這樣的:
<?php $route = new Zend_Controller_Router_Route( 'author/:username', array( 'controller' => 'profile', 'action' => 'userinfo' ) ); $router->addRoute('user', $route);
在Zend_Controller_Router_Route裡構造函數的第一個參數是路由的定義,它將匹配一個URL。路由定義包含靜態的和動態部分,它們由正斜槓('/')符分開。靜態部分只是簡單的字符:author。動態部分,被叫做變量,用預設的冒號來標記變量名::username。
當你把浏覽器指向http://domain.com/author/martel這個例子的路由應該被匹配,它所有的變量將被注入到Zend_Controller_Request對象並在ProfileController可訪問。由這個例子返回的變量可能會被表示為如下鍵和值配對的數組:
<?php $values = array( 'username' => 'martel', 'controller' => 'profile', 'action' => 'userinfo' );
稍後,基於這些值,Zend_Controller_Dispatcher_Standard應該調用ProfileController類(在缺省模塊中)中的userinfoAction()方法。你將依靠Zend_Controller_Action::_getParam()或者Zend_Controller_Request::getParam()方法能夠訪問所有的變量:
<?php public function userinfoAction() { $request = $this->getRequest(); $username = $request->getParam('username'); $username = $this->_getParam('username'); }
路由定義可以包一個額外的特別字符-通配符-表示為'*'號。它被用來取得參數,和缺省模塊路由類似(在URI中定義的var=>value)。下面的路由多多少少地模仿了模塊路由的行為:
<?php $route = new Zend_Controller_Router_Route( ':module/:controller/:action/*', array('module' => 'default') ); $router->addRoute('default', $route);
當變量請求被設定,第三個參數可以加給Zend_Controller_Router_Route的構造函數。這些被定義為正則表達式的一部分:
<?php $route = new Zend_Controller_Router_Route( 'archive/:year', array( 'year' => 2006, 'controller' => 'archive', 'action' => 'show' ), array('year' => '\d+') ); $router->addRoute('archive', $route);
用上述定義的路由,路由器僅當year變量包含數字數據將匹配它,例如http://domain.com/archive/2345。象http://example.com/archive/test這樣的URL將不被匹配並且控制將被傳遞給在鏈中的下一個路由。
<ul id="nav"> <li><a href="<?php echo $this->url(array('controller'=>'index'),null,true);?>" title="Home">首頁</a></li> <li><a href="<?php echo $this->url(array('controller'=>'news','action'=>'index'),null,true);?>" title="news">新聞</a></li> </ul>