2
0

Zend_Controller-Router.xml 21 KB

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