Zend_Controller-Router.xml 20 KB

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