2
0

Zend_Controller-Router.xml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <sect1 id="zend.controller.router" xmlns:xi="http://www.w3.org/2001/XInclude">
  2. <title>标准路由器</title>
  3. <sect2 id="zend.controller.router.introduction">
  4. <title>简介</title>
  5. <para>
  6. <code>Zend_Controller_Router_Rewrite</code>是标准的框架路由器。路由是个过程,在这个过程中它取出URI的端点(跟着基本URL的URI的那部分)并把它分解成参数来决定哪个模块、哪个控制器和控制器中的哪个动作应该接受请求。模块、控制器、动作和其它参数被打包到<code>Zend_Controller_Request_Http</code>对象,接着这个对象由<code>Zend_Controller_Dispatcher_Standard</code>来处理。路由只发生一次:当请求最初被接收和第一个控制器被派遣之前。
  7. </para>
  8. <para>
  9. <code>Zend_Controller_Router_Rewrite</code>被设计来考虑使用纯php结构时mod_rewrite-like的功能性。它非常宽松地基于Ruby on Rails并且不要求任何先前的web服务器URL rewriting的知识。它被设计来和单个Apache的 mod_rewrite规则(其中之一)一起工作:
  10. </para>
  11. <programlisting role="php"><![CDATA[
  12. RewriteEngine on
  13. RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
  14. ]]>
  15. </programlisting>
  16. <para>
  17. 或者:
  18. </para>
  19. <programlisting role="php"><![CDATA[
  20. RewriteEngine on
  21. RewriteCond %{SCRIPT_FILENAME} !-f
  22. RewriteCond %{SCRIPT_FILENAME} !-d
  23. RewriteRule ^(.*)$ index.php/$1
  24. ]]>
  25. </programlisting>
  26. <para>
  27. 如果<ulink url="http://www.isapirewrite.com">Isapi_Rewrite</ulink>已经用下列的rewrite规则被安装为一个Isapi扩展, rewrite路由器也可以和IIS web服务器一起使用:
  28. </para>
  29. <programlisting role="php"><![CDATA[
  30. RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css)$)[\w\%]*$)? /index.php [I]
  31. ]]>
  32. </programlisting>
  33. <note>
  34. <title>IIS Isapi_Rewrite</title>
  35. <para>
  36. 当使用IIS,<code>$_SERVER['REQUEST_URI']</code>将要么不存在,要么被设置成一个空串。在这个例子中,<code>Zend_Controller_Request_Http</code>将企图使用被Isapi_Rewrite扩展设置的<code>$_SERVER['HTTP_X_REWRITE_URL']</code>的值。
  37. </para>
  38. </note>
  39. <para>
  40. 如果使用 Lighttpd,下面的 rewrite 规则有效:
  41. </para>
  42. <programlisting role="lighttpd"><![CDATA[
  43. url.rewrite-once = (
  44. ".*\?(.*)$" => "/index.php?$1",
  45. ".*\.(js|ico|gif|jpg|png|css)$" => "$0",
  46. "" => "/index.php"
  47. )
  48. ]]>
  49. </programlisting>
  50. </sect2>
  51. <sect2 id="zend.controller.router.usage">
  52. <title>使用路由器</title>
  53. <para>
  54. 为正确使用rewrite路由器你必须初始化它,添加一些用户定义的路由并注入到控制器。下面的代码示例这个过程:
  55. </para>
  56. <programlisting role="php"><![CDATA[
  57. // Create a router
  58. $router = $ctrl->getRouter(); // returns a rewrite router by default
  59. $router->addRoute(
  60. 'user',
  61. new Zend_Controller_Router_Route('user/:username',
  62. array('controller' => 'user',
  63. 'action' => 'info'))
  64. );
  65. ]]>
  66. </programlisting>
  67. </sect2>
  68. <sect2 id="zend.controller.router.basic">
  69. <title>基本的Rewrite路由器操作</title>
  70. <para>
  71. RewriteRouter的核心是用户定义路由的定义。路由通过调用RewriteRouter的addRoute方法和传递一个由类实现的<code>Zend_Controller_Router_Route_Interface</code>的新的实例被添加。例如:
  72. </para>
  73. <programlisting role="php"><![CDATA[
  74. $router->addRoute('user',
  75. new Zend_Controller_Router_Route('user/:username'));
  76. ]]>
  77. </programlisting>
  78. <para>
  79. Rewrite 路由器带有四个基本类型的路由(其中一个是特殊的):
  80. </para>
  81. <itemizedlist mark="opencircle">
  82. <listitem><para><xref linkend="zend.controller.router.routes.standard" /></para></listitem>
  83. <listitem><para><xref linkend="zend.controller.router.routes.static" /></para></listitem>
  84. <listitem><para><xref linkend="zend.controller.router.routes.regex" /></para></listitem>
  85. <listitem><para><xref linkend="zend.controller.router.default-routes" /> *</para></listitem>
  86. </itemizedlist>
  87. <para>
  88. 路由可以被使用无数次来创建链或用户定义的应用程序路由计划。你可以在任何配置中使用任何数量的路由,除了模块路由以外,它最好被用一次并作为通用路由(例如,作为缺省的)。每个路由将在稍后详细描述。
  89. </para>
  90. <para>
  91. addRoute的第一个参数是路由名。它用来作为权柄从路由器中取得路由(例如,for URL generation purposes)。第二个参数是路由自己。
  92. </para>
  93. <note>
  94. <para>
  95. 路由名最普通的用法是通过Zend_View_url助手的方法:
  96. </para>
  97. <programlisting role="php"><![CDATA[
  98. "<?= $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
  99. ]]>
  100. </programlisting>
  101. <para>
  102. 它将导致在 href: <code>user/martel</code>.
  103. </para>
  104. </note>
  105. <para>
  106. 路由是一个简单的过程,这个过程通过所有提供的路由和匹配它的当前请求的URI定义来迭代。当一个正匹配被发现,变量值从路由实例返回并注入到<code>Zend_Controller_Request</code>对象以备将来在派遣器和用户创建的控制器中使用。如果是负匹配,在链中的下个路由被检查。
  107. </para>
  108. <note>
  109. <title>倒序匹配</title>
  110. <para>
  111. 用倒序来匹配路由确保最通用的路由被首先定义。
  112. </para>
  113. </note>
  114. <note>
  115. <title>返回的值</title>
  116. <para>
  117. 从路由返回的值来自于URL参数或用于定义的缺省值。这些变量以后可通过<code>Zend_Controller_Request::getParam()</code> 或 <code>Zend_Controller_Action::_getParam()</code> 方法来访问。
  118. </para>
  119. </note>
  120. <para>
  121. 有三个特殊的变量可用于你的路由-'module'、 'controller' 和 'action'。这些特殊的变量被Zend_Controller_Dispatcher用来找出控制器和动作然后派遣过去。
  122. </para>
  123. <note>
  124. <title>特殊变量</title>
  125. <para>
  126. 如果你选择通过 <code>setControllerKey</code> 和 <code>setActionKey</code>方法的方式来改变缺省值,这些特殊变量的名字可能会不同。
  127. </para>
  128. </note>
  129. </sect2>
  130. <sect2 id="zend.controller.router.default-routes">
  131. <title>缺省路由</title>
  132. <para>
  133. Zend_Controller_Router_Rewrite 和缺省路由一起预先配置,它将以<code>controller/action</code>的形式匹配URIs。另外,模块名可以被指定作为第一个路径参数,允许这种<code>module/controller/action</code>形式的URIs。最后,它也将缺省地匹配任何另外的追加到URI的参数-<code>controller/action/var1/value1/var2/value2</code>。
  134. </para>
  135. <para>
  136. 一些路由如何匹配的例子:
  137. </para>
  138. <programlisting role="php"><![CDATA[
  139. // Assuming the following:
  140. $ctrl->setControllerDirectory(
  141. array(
  142. 'default' => '/path/to/default/controllers',
  143. 'news' => '/path/to/news/controllers',
  144. 'blog' => '/path/to/blog/controllers'
  145. )
  146. );
  147. Module only:
  148. http://example/news
  149. module == news
  150. Invalid module maps to controller name:
  151. http://example/foo
  152. controller == foo
  153. Module + controller:
  154. http://example/blog/archive
  155. module == blog
  156. controller == archive
  157. Module + controller + action:
  158. http://example/blog/archive/list
  159. module == blog
  160. controller == archive
  161. action == list
  162. Module + controller + action + params:
  163. http://example/blog/archive/list/sort/alpha/date/desc
  164. module == blog
  165. controller == archive
  166. action == list
  167. sort == alpha
  168. date == desc
  169. ]]>
  170. </programlisting>
  171. <para>
  172. 缺省路由是存储在RewriteRouter名(index)为'default'的简单的<code>Zend_Controller_Router_Route_Module</code>对象。它被创建多多少少象下面这样:
  173. </para>
  174. <programlisting role="php"><![CDATA[
  175. $compat = new Zend_Controller_Router_Route_Module(array(),
  176. $dispatcher,
  177. $request);
  178. $this->addRoute('default', $compat);
  179. ]]>
  180. </programlisting>
  181. <para>
  182. 如果你不想这个特别的缺省路由在你的路由计划中,你可以重写你自己的‘缺省’路由(例如,把它存储在'default'名下)或用<code>removeDefaultRoutes()</code>完全清除它:
  183. </para>
  184. <programlisting role="php"><![CDATA[
  185. // Remove any default routes
  186. $router->removeDefaultRoutes();
  187. ]]>
  188. </programlisting>
  189. </sect2>
  190. <sect2 id="zend.controller.router.rewritebase">
  191. <title>基本 URL 和子目录</title>
  192. <para>
  193. rewrite路由器可以被用在子目录(例如,<code>http://domain.com/~user/application-root/</code>),在此例中,应用程序 (<code>/~user/application-root</code>)的基本URL应该能自动被<code>Zend_Controller_Request_Http</code>检测到并使用。
  194. </para>
  195. <para>
  196. 如果基本URL被误删除,你可以通过<code>Zend_Controller_Request_Http</code> 和调用 <code>setBaseUrl()</code> 方法(参见<xref linkend="zend.controller.request.http.baseurl" />)用你自己的基本路径重写它。
  197. </para>
  198. <programlisting role="php"><![CDATA[
  199. $request->setBaseUrl('/~user/application-root/');
  200. ]]>
  201. </programlisting>
  202. </sect2>
  203. <sect2 id="zend.controller.router.routes">
  204. <title>Route Types</title>
  205. <xi:include href="Zend_Controller-Router-Route.xml" />
  206. <xi:include href="Zend_Controller-Router-Route-Static.xml" />
  207. <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
  208. </sect2>
  209. <sect2 id="zend.controller.router.add-config">
  210. <title>使用 Zend_Config with the RewriteRouter</title>
  211. <para>
  212. 有时候,用新路由更新配置文件比修改代码更方便。这个可能通过<code>addConfig()</code>方法来做。基本上,你创建一个Zend_Config-compatible配置,并在你的代码中读入然后传递给RewriteRouter。
  213. </para>
  214. <para>
  215. 作为例子,考虑下面的 INI 文件:
  216. </para>
  217. <programlisting role="php"><![CDATA[
  218. [production]
  219. routes.archive.route = "archive/:year/*"
  220. routes.archive.defaults.controller = archive
  221. routes.archive.defaults.action = show
  222. routes.archive.defaults.year = 2000
  223. routes.archive.reqs.year = "\d+"
  224. routes.news.type = "Zend_Controller_Router_Route_Static"
  225. routes.news.route = "news"
  226. routes.news.defaults.controller = "news"
  227. routes.news.defaults.action = "list"
  228. routes.archive.type = "Zend_Controller_Router_Route_Regex"
  229. routes.archive.route = "archive/(\d+)"
  230. routes.archive.defaults.controller = "archive"
  231. routes.archive.defaults.action = "show"
  232. routes.archive.map.1 = "year"
  233. ; OR: routes.archive.map.year = 1
  234. ]]>
  235. </programlisting>
  236. <para>
  237. 上述的INI文件可以被读进<code>Zend_Config</code>对象:
  238. </para>
  239. <programlisting role="php"><![CDATA[
  240. $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
  241. $router = new Zend_Controller_Router_Rewrite();
  242. $router->addConfig($config, 'routes');
  243. ]]>
  244. </programlisting>
  245. <para>
  246. 在上面的例子中,我们告诉路由器去使用INI文件'routes'一节给它的路由。每个在这个节下的顶级键将用来定义路由名;上述例子定义了路由'archive'和'news'。每个路由接着要求,至少,一个'route'条目和一个或更多'defaults'条目;可选地,一个或更多'reqs'('required'的简写)可能要求提供。总之,这些相对应的三个参数提供给<code>Zend_Controller_Router_Route_Interface</code>对象。一个选项键,'type',可用来指定路由类的类型给特殊的路由;缺省地,它使用<code>Zend_Controller_Router_Route</code>。在上述例子中,'news'路由被定义来使用<code>Zend_Controller_Router_Route_Static</code>。
  247. </para>
  248. </sect2>
  249. <sect2 id="zend.controller.router.subclassing">
  250. <title>Subclassing the Router</title>
  251. <para>
  252. 标准的rewrite路由器应当最大限度提供你所需的功能;大多时候,为了通过已知的路由提供新的或修改的功能,你将只需要创建一个新的路由类型
  253. </para>
  254. <para>
  255. 那就是说,你可能想要用不同的路由范例。接口<code>Zend_Controller_Router_Interface</code>提供了需要最少的信息来创建路由器,并包含一个单个的方法。
  256. </para>
  257. <programlisting role="php"><![CDATA[
  258. interface Zend_Controller_Router_Interface
  259. {
  260. /**
  261. * @param Zend_Controller_Request_Abstract $request
  262. * @throws Zend_Controller_Router_Exception
  263. * @return Zend_Controller_Request_Abstract
  264. */
  265. public function route(Zend_Controller_Request_Abstract $request);
  266. }
  267. ]]>
  268. </programlisting>
  269. <para>
  270. 路由只发生一次:当请求第一次接收到系统。路由器的意图是基于请求的环境决定控制器、动作和可选的参数,并把它们发给请求。请求对象接着传递给派遣器。如果不可能映射一个路由到一个派遣令牌,路由器对请求对象就什么也不做。
  271. </para>
  272. </sect2>
  273. </sect1>
  274. <!--
  275. vim:se ts=4 sw=4 et:
  276. -->