Zend_Controller-Router.xml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="zend.controller.router" xmlns:xi="http://www.w3.org/2001/XInclude">
  4. <title>El Router Standard</title>
  5. <sect2 id="zend.controller.router.introduction">
  6. <title>Introducción</title>
  7. <para>
  8. <classname>Zend_Controller_Router_Rewrite</classname> Es el router
  9. standard del Framework. Routing es el proceso de tomar la parte
  10. final de una URI (la parte de la URI que viene después de la URL
  11. base) y la descomposición en parámetros para determinar qué módulo,
  12. qué controlador y acción de ese controlador debe recibir la solicitud.
  13. Estos valores del módulo, controlador, acción y otros parámetros
  14. están enpaquetados en un objeto
  15. <classname>Zend_Controller_Request_Http</classname> el cual es
  16. procesado luego por <classname>Zend_Controller_Dispatcher_Standard</classname>.
  17. El routing ocurre sólo una vez: cuando se recibió inicialmente la
  18. solicitud y antes del dispatch del primer controlador.
  19. </para>
  20. <para>
  21. <classname>Zend_Controller_Router_Rewrite</classname> está diseñado
  22. para permitir que una funcionalidad tipo mod_rewrite se pueda usar
  23. en estructuras PHP puras. Se basa muy vagamente en el routing de
  24. Ruby on Rails (RoR) y no requiere ningún conocimiento previo de
  25. reescritura de la URL del webserver. Está diseñado para trabajar
  26. con solo una regla mod_rewrite de Apache (one of):
  27. </para>
  28. <programlisting role="php"><![CDATA[
  29. RewriteEngine on
  30. RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
  31. ]]></programlisting>
  32. <para>
  33. o (preferido):
  34. </para>
  35. <programlisting role="php"><![CDATA[
  36. RewriteEngine On
  37. RewriteCond %{REQUEST_FILENAME} -s [OR]
  38. RewriteCond %{REQUEST_FILENAME} -l [OR]
  39. RewriteCond %{REQUEST_FILENAME} -d
  40. RewriteRule ^.*$ - [NC,L]
  41. RewriteRule ^.*$ index.php [NC,L]
  42. ]]></programlisting>
  43. <para>
  44. El router rewrite también puede utilizarse con el IIS webserver (versions &lt;= 7.0) si <ulink
  45. url="http://www.isapirewrite.com">Isapi_Rewrite</ulink>
  46. se ha instalado como una extensión Isapi con la siguiente
  47. regla de reescribir:
  48. </para>
  49. <programlisting role="php"><![CDATA[
  50. RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css|html)$)[\w\%]*$)? /index.php [I]
  51. ]]></programlisting>
  52. <note>
  53. <title>IIS Isapi_Rewrite</title>
  54. <para>
  55. Cuando se usa IIS, <code>$_SERVER['REQUEST_URI']</code> puede
  56. no existir, o establecerlo como un string vacío. En este caso,
  57. <classname>Zend_Controller_Request_Http</classname>
  58. intentará usar el valor de
  59. <code>$_SERVER['HTTP_X_REWRITE_URL']</code>
  60. establecido por la extensión Isapi_Rewrite.
  61. </para>
  62. </note>
  63. <para>
  64. IIS 7.0 introduce un módulo nativo de reescribir la URL, y puede ser
  65. configurado como sigue:
  66. </para>
  67. <programlisting role="xml"><![CDATA[
  68. <?xml version="1.0" encoding="UTF-8"?>
  69. <configuration>
  70. <system.webServer>
  71. <rewrite>
  72. <rules>
  73. <rule name="Imported Rule 1" stopProcessing="true">
  74. <match url="^.*$" />
  75. <conditions logicalGrouping="MatchAny">
  76. <add input="{REQUEST_FILENAME}"
  77. matchType="IsFile" pattern=""
  78. ignoreCase="false" />
  79. <add input="{REQUEST_FILENAME}"
  80. matchType="IsDirectory"
  81. pattern="" ignoreCase="false" />
  82. </conditions>
  83. <action type="None" />
  84. </rule>
  85. <rule name="Imported Rule 2" stopProcessing="true">
  86. <match url="^.*$" />
  87. <action type="Rewrite" url="index.php" />
  88. </rule>
  89. </rules>
  90. </rewrite>
  91. </system.webServer>
  92. </configuration>]></programlisting>
  93. <para>
  94. Si está usando Lighttpd, la siguiente regla de reescritura es válida:
  95. </para>
  96. <programlisting role="lighttpd"><![CDATA[
  97. url.rewrite-once = (
  98. ".*\?(.*)$" => "/index.php?$1",
  99. ".*\.(js|ico|gif|jpg|png|css|html)$" => "$0",
  100. "" => "/index.php"
  101. )
  102. ]]></programlisting>
  103. </sect2>
  104. <sect2 id="zend.controller.router.usage">
  105. <title>Usando un Router</title>
  106. <para>
  107. Para utilizar adecuadamente el router de reescritura debe
  108. instanciarlo, agregar algunas rutas definidas por el usuario y
  109. luego inyectarlo en el controlador. El siguiente código ilustra el
  110. procedimiento:
  111. </para>
  112. <programlisting role="php"><![CDATA[
  113. // Crear un router
  114. $router = $ctrl->getRouter(); // returns a rewrite router by default
  115. $router->addRoute(
  116. 'user',
  117. new Zend_Controller_Router_Route('user/:username',
  118. array('controller' => 'user',
  119. 'action' => 'info'))
  120. );
  121. ]]></programlisting>
  122. </sect2>
  123. <sect2 id="zend.controller.router.basic">
  124. <title>Operación Básica del Rewrite Router</title>
  125. <para>
  126. El corazón del RewriteRouter es la definición de la rutas definidas
  127. por el usuario. Las rutas se agregan llamando al método addRoute
  128. de RewriteRouter y pasándole una nueva instancia de una clase que
  129. implementó a
  130. <classname>Zend_Controller_Router_Route_Interface</classname>. Eg.:
  131. </para>
  132. <programlisting role="php"><![CDATA[
  133. $router->addRoute('user',
  134. new Zend_Controller_Router_Route('user/:username'));
  135. ]]></programlisting>
  136. <para>
  137. El Rewrite Router viene con seis tipos básicos de rutas (uno de los
  138. cuales es especial):
  139. </para>
  140. <itemizedlist mark="opencircle">
  141. <listitem><para><xref linkend="zend.controller.router.routes.standard" /></para></listitem>
  142. <listitem><para><xref linkend="zend.controller.router.routes.static" /></para></listitem>
  143. <listitem><para><xref linkend="zend.controller.router.routes.regex" /></para></listitem>
  144. <listitem><para><xref linkend="zend.controller.router.routes.hostname" /></para></listitem>
  145. <listitem><para><xref linkend="zend.controller.router.routes.chain" /></para></listitem>
  146. <listitem><para><xref linkend="zend.controller.router.default-routes" /> *</para></listitem>
  147. </itemizedlist>
  148. <para>
  149. Las rutas pueden ser utilizadas numerosas veces para crear una cadena
  150. o un esquema de aplicación de ruteo definido por el usuario.
  151. Puede usar cualquier número de rutas en cualquier configuración,
  152. con la excepción de la ruta del Módulo, la cual debe ser utilizada
  153. una vez y probablemente como la ruta más genérica (es decir,
  154. por defecto). Cada ruta se describe en mayor detalle más adelante.
  155. </para>
  156. <para>
  157. El primer parámetro a addRoute es el nombre de la ruta.
  158. Se utiliza como un manejador para sacar las rutas del router
  159. (por ejemplo, con fines de generación de URL).
  160. El segundo parámetro es la ruta misma.
  161. </para>
  162. <note>
  163. <para>
  164. El uso más común del nombre de ruta es por medio del
  165. ayudante de url <classname>Zend_View</classname>:
  166. </para>
  167. <programlisting role="php"><![CDATA[
  168. <a href=
  169. "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
  170. ]]></programlisting>
  171. <para>
  172. Que resultaría en la href: <code>user/martel</code>.
  173. </para>
  174. </note>
  175. <para>
  176. El routing es un simple proceso de iteración a través de todas las
  177. rutas provistas y la equiparación de sus definiciones con la petición
  178. actual de URI. Cuando se encuentra una concordancia, se devuelven
  179. valores de variables desde la instancia Route y se inyecta en el
  180. objeto <classname>Zend_Controller_Request</classname>
  181. para su posterior utilización en el dispatcher así también como en
  182. los controladores creados por el usuario. En caso de no encontrar
  183. ninguna concordancia, se comprobará la siguiente ruta en la cadena.
  184. </para>
  185. <para>
  186. Si necesita determinar en qué ruta se encontró una concordancia,
  187. puede usar el método <code>getCurrentRouteName()</code>, que devolverá
  188. el identificador usado cuando registró la ruta con el router.
  189. Si quiere el objeto de la ruta actual, puede usar
  190. <code>getCurrentRoute()</code>.
  191. </para>
  192. <note>
  193. <title>Matching Inverso</title>
  194. <para>
  195. Las rutas están equiparadas en orden inverso para asegurarse
  196. que las rutas más genéricas se definan primero.
  197. </para>
  198. </note>
  199. <note>
  200. <title>Valores Retornados</title>
  201. <para>
  202. Los valores retornados del routing provienen de parámetros URL
  203. o de rutas definidas por defecto por el usuario.
  204. Estas variables son accesibles posteriormente a través de los métodos
  205. <classname>Zend_Controller_Request::getParam()</classname> o
  206. <classname>Zend_Controller_Action::_getParam()</classname>.
  207. </para>
  208. </note>
  209. <para>
  210. Hay tres variables que pueden utilizarse en las rutas - 'module',
  211. 'controller' y 'action'. Estas variables especiales son utilizados por
  212. <classname>Zend_Controller_Dispatcher</classname> para encontrar un
  213. controlador y una acción para hacer el dispatch.
  214. </para>
  215. <note>
  216. <title>Variables Especiales</title>
  217. <para>
  218. Los nombres de estas variables especiales pueden ser diferentes
  219. si elige alterar los valores por defecto en
  220. <classname>Zend_Controller_Request_Http</classname> mediante los
  221. métodos
  222. <code>setControllerKey</code> y <code>setActionKey</code>.
  223. </para>
  224. </note>
  225. </sect2>
  226. <sect2 id="zend.controller.router.default-routes">
  227. <title>Routes por Defecto</title>
  228. <para>
  229. <classname>Zend_Controller_Router_Rewrite</classname> viene
  230. preconfigurado con una ruta por defecto, que se comparará con URIs
  231. en la forma de <code>controller/action</code>.
  232. Además, se puede especificar un nombre de módulo como primer
  233. elemento del path, permitiendo URIs de la forma
  234. <code>module/controller/action</code>. Por último, también coincidrá
  235. con cualquier parámetro adicional agregado a la URI por defecto -
  236. <code>controller/action/var1/value1/var2/value2</code>.
  237. </para>
  238. <para>
  239. Algunos ejemplos de cómo están equiparadas las rutas:
  240. </para>
  241. <programlisting role="php"><![CDATA[
  242. // Asumiendo lo siguiente:
  243. $ctrl->setControllerDirectory(
  244. array(
  245. 'default' => '/path/to/default/controllers',
  246. 'news' => '/path/to/news/controllers',
  247. 'blog' => '/path/to/blog/controllers'
  248. )
  249. );
  250. Módulo únicamente:
  251. http://example/news
  252. module == news
  253. Modulo inválido mapea al nombre del controlador:
  254. http://example/foo
  255. controller == foo
  256. Módulo + controlador:
  257. http://example/blog/archive
  258. module == blog
  259. controller == archive
  260. Módulo + controlador + accción:
  261. http://example/blog/archive/list
  262. module == blog
  263. controller == archive
  264. action == list
  265. Módulo + controlador + accción + parámetros:
  266. http://example/blog/archive/list/sort/alpha/date/desc
  267. module == blog
  268. controller == archive
  269. action == list
  270. sort == alpha
  271. date == desc
  272. ]]></programlisting>
  273. <para>
  274. La ruta por defecto es simplemente un objeto
  275. <classname>Zend_Controller_Router_Route_Module</classname>
  276. almacenado bajo el nombre de (index) por 'default' en RewriteRouter.
  277. Está generado más o menos así:
  278. </para>
  279. <programlisting role="php"><![CDATA[
  280. $compat = new Zend_Controller_Router_Route_Module(array(),
  281. $dispatcher,
  282. $request);
  283. $this->addRoute('default', $compat);
  284. ]]></programlisting>
  285. <para>
  286. Si no quiere esta ruta en particular en su esquema por defecto de
  287. routing, podrá anularla creando su propia ruta por 'defecto'
  288. (es decir, almacenar bajo el nombre de 'default') o eliminarla por
  289. completo usando <code>removeDefaultRoutes()</code>:
  290. </para>
  291. <programlisting role="php"><![CDATA[
  292. // Eliminar cualquier ruta por defecto
  293. $router->removeDefaultRoutes();
  294. ]]></programlisting>
  295. </sect2>
  296. <sect2 id="zend.controller.router.rewritebase">
  297. <title>URL Base y Subdirectorios</title>
  298. <para>
  299. El router rewrite puede ser utilizado en subdirectorios (por
  300. ejemplo <code>http://domain.com/~user/application-root/</code>)
  301. en cuyo caso la URL base de la aplicación
  302. (<code>/~user/application-root</code>) debe ser detectada
  303. automáticamente por <classname>Zend_Controller_Request_Http</classname>
  304. y usada en consecuencia.
  305. </para>
  306. <para>
  307. Si la URL base se detecta incorrectamente se la puede anular con su
  308. propio path de base usando
  309. <classname>Zend_Controller_Request_Http</classname> y llamando al
  310. método <code>setBaseUrl()</code> (ver <xref
  311. linkend="zend.controller.request.http.baseurl" />):
  312. </para>
  313. <programlisting role="php"><![CDATA[
  314. $request->setBaseUrl('/~user/application-root/');
  315. ]]></programlisting>
  316. </sect2>
  317. <sect2 id="zend.controller.router.global.parameters">
  318. <title>Parámetros Globales</title>
  319. <para>
  320. Puede establecer los parámetros globales en un router que se
  321. proporcionan automáticamente a una ruta cuando se ensamblasn mediante
  322. <code>setGlobalParam</code>. Si se establece un parámetro global
  323. pero también se lo entrega directamente al método de ensamblaje,
  324. el parámetro del usuario sobreescribe al parámetro global.
  325. Puede establecer un parámetro global esta forma:
  326. </para>
  327. <programlisting role="php"><![CDATA[
  328. $router->setGlobalParam('lang', 'en');
  329. ]]></programlisting>
  330. </sect2>
  331. <sect2 id="zend.controller.router.routes">
  332. <title>Tipos de Route</title>
  333. <xi:include href="Zend_Controller-Router-Route.xml" />
  334. <xi:include href="Zend_Controller-Router-Route-Static.xml" />
  335. <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
  336. <xi:include href="Zend_Controller-Router-Route-Hostname.xml" />
  337. <xi:include href="Zend_Controller-Router-Route-Chain.xml" />
  338. </sect2>
  339. <sect2 id="zend.controller.router.add-config">
  340. <title>Usando <classname>Zend_Config</classname> con RewriteRouter</title>
  341. <para>
  342. A veces es más conveniente para actualizar un archivo de
  343. configuración con nuevas rutas que modificar el código.
  344. Esto es posible a través del método <code>addConfig()</code>.
  345. Básicamente, se crea una configuración compatible con
  346. <classname>Zend_Config</classname>.
  347. Y en su código lo lee y lo pasa a RewriteRouter.
  348. </para>
  349. <para>
  350. Como ejemplo, considere el siguiente archivo INI:
  351. </para>
  352. <programlisting role="php"><![CDATA[
  353. [production]
  354. routes.archive.route = "archive/:year/*"
  355. routes.archive.defaults.controller = archive
  356. routes.archive.defaults.action = show
  357. routes.archive.defaults.year = 2000
  358. routes.archive.reqs.year = "\d+"
  359. routes.news.type = "Zend_Controller_Router_Route_Static"
  360. routes.news.route = "news"
  361. routes.news.defaults.controller = "news"
  362. routes.news.defaults.action = "list"
  363. routes.archive.type = "Zend_Controller_Router_Route_Regex"
  364. routes.archive.route = "archive/(\d+)"
  365. routes.archive.defaults.controller = "archive"
  366. routes.archive.defaults.action = "show"
  367. routes.archive.map.1 = "year"
  368. ; O: routes.archive.map.year = 1
  369. ]]></programlisting>
  370. <para>
  371. Entonces el archivo INI puede ser leído por un objeto
  372. <classname>Zend_Config</classname> como sigue:
  373. </para>
  374. <programlisting role="php"><![CDATA[
  375. $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
  376. $router = new Zend_Controller_Router_Rewrite();
  377. $router->addConfig($config, 'routes');
  378. ]]></programlisting>
  379. <para>
  380. En el ejemplo de arriba, le decimos el router que utilice la
  381. sección 'routes' del archivo INI para utilizarlo en sus rutas.
  382. Cada clave de primer nivel en esa sección será utilizada para definir
  383. un nombre de ruta; el ejemplo anterior define las rutas 'archive' y
  384. 'news'. Entonces cada ruta requiere, como mínimo, una entrada a la
  385. 'ruta' y una o más entradas por 'default'; opcionalmente puede
  386. proporcionarse una o más 'reqs' (abreviación de 'required').
  387. Dicho todo esto, estos corresponden a los tres argumentos que se le
  388. suministran al objeto
  389. <classname>Zend_Controller_Router_Route_Interface</classname>.
  390. Puede utilizarse una clave opcional 'type' para especificar el
  391. tipo de clase de ruta a utilizar en esa ruta en particular;
  392. por defecto, usa
  393. <classname>Zend_Controller_Router_Route</classname>.
  394. En el ejemplo de arriba, la ruta 'news' está definida para usar
  395. <classname>Zend_Controller_Router_Route_Static</classname>.
  396. </para>
  397. </sect2>
  398. <sect2 id="zend.controller.router.subclassing">
  399. <title>Subclassing del Router</title>
  400. <para>
  401. El standard rewrite router debería proporcionarle más funcionalidad
  402. si la necesita; más a menudo, sólo necesitará crear un nuevo
  403. tipo de ruta a fin de ofrecer funcionalidades nuevas o modificadas
  404. sobre las tutas provistas.
  405. </para>
  406. <para>
  407. Dicho esto, en algún momento puede encontrarse a si mismo deseando
  408. usar un paradigma diferente de routing. La intefaz
  409. <classname>Zend_Controller_Router_Interface</classname> proporciona
  410. la información mínima necesaria para crear un router, y consiste en
  411. un único método.
  412. </para>
  413. <programlisting role="php"><![CDATA[
  414. interface Zend_Controller_Router_Interface
  415. {
  416. /**
  417. * @param Zend_Controller_Request_Abstract $request
  418. * @throws Zend_Controller_Router_Exception
  419. * @return Zend_Controller_Request_Abstract
  420. */
  421. public function route(Zend_Controller_Request_Abstract $request);
  422. }
  423. ]]></programlisting>
  424. <para>
  425. El routing sólo ocurre una vez: cuando la petición es recibida por
  426. primera vez en el sistema. El propósito del router es determinar el
  427. controlador, la acción, y los parámetros opcionales sobre la base
  428. del medio ambiente de la solicitud, y luego ajustarlos en la solicitud.
  429. El objeto solicitud se pasa entonces al dispatcher.
  430. Si no es posible trazar una ruta hacia un dispatch token,
  431. el router no debe hacer nada con el objeto solicitud.
  432. </para>
  433. </sect2>
  434. </sect1>
  435. <!--
  436. vim:se ts=4 sw=4 et:
  437. -->