Zend_Controller-Router.xml 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 18940 -->
  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 <acronym>URI</acronym> que viene después de la <acronym>URL</acronym>
  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 <acronym>PHP</acronym> 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 <acronym>URL</acronym> del webserver. Está diseñado para trabajar
  27. con solo una regla mod_rewrite de Apache (one of):
  28. </para>
  29. <programlisting language="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 language="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 <acronym>IIS</acronym> 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 language="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 <acronym>IIS</acronym>, <varname>$_SERVER['REQUEST_URI']</varname> 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. <varname>$_SERVER['HTTP_X_REWRITE_URL']</varname>
  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 language="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 language="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 language="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 language="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>
  143. <para>
  144. <link
  145. linkend="zend.controller.router.routes.standard">Zend_Controller_Router_Route</link>
  146. </para>
  147. </listitem>
  148. <listitem>
  149. <para>
  150. <link
  151. linkend="zend.controller.router.routes.static">Zend_Controller_Router_Route_Static</link>
  152. </para>
  153. </listitem>
  154. <listitem>
  155. <para>
  156. <link
  157. linkend="zend.controller.router.routes.regex">Zend_Controller_Router_Route_Regex</link>
  158. </para>
  159. </listitem>
  160. <listitem>
  161. <para>
  162. <link
  163. linkend="zend.controller.router.routes.hostname">Zend_Controller_Router_Route_Hostname</link>
  164. </para>
  165. </listitem>
  166. <listitem>
  167. <para>
  168. <link
  169. linkend="zend.controller.router.routes.chain">Zend_Controller_Router_Route_Chain</link>
  170. </para>
  171. </listitem>
  172. <listitem>
  173. <para>
  174. <link
  175. linkend="zend.controller.router.default-routes">Zend_Controller_Router_Rewrite</link>
  176. *
  177. </para>
  178. </listitem>
  179. </itemizedlist>
  180. <para>
  181. Las rutas pueden ser utilizadas numerosas veces para crear una cadena
  182. o un esquema de aplicación de ruteo definido por el usuario.
  183. Puede usar cualquier número de rutas en cualquier configuración,
  184. con la excepción de la ruta del Módulo, la cual debe ser utilizada
  185. una vez y probablemente como la ruta más genérica (es decir,
  186. por defecto). Cada ruta se describe en mayor detalle más adelante.
  187. </para>
  188. <para>
  189. El primer parámetro a addRoute es el nombre de la ruta.
  190. Se utiliza como un manejador para sacar las rutas del router
  191. (por ejemplo, con fines de generación de <acronym>URL</acronym>).
  192. El segundo parámetro es la ruta misma.
  193. </para>
  194. <note>
  195. <para>
  196. El uso más común del nombre de ruta es por medio del
  197. ayudante de <acronym>URL</acronym> <classname>Zend_View</classname>:
  198. </para>
  199. <programlisting language="php"><![CDATA[
  200. <a href=
  201. "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
  202. ]]></programlisting>
  203. <para>
  204. Que resultaría en la href: <methodname>user/martel</methodname>.
  205. </para>
  206. </note>
  207. <para>
  208. El routing es un simple proceso de iteración a través de todas las
  209. rutas provistas y la equiparación de sus definiciones con la petición
  210. actual de <acronym>URI</acronym>. Cuando se encuentra una concordancia, se devuelven
  211. valores de variables desde la instancia Route y se inyecta en el
  212. objeto <classname>Zend_Controller_Request</classname>
  213. para su posterior utilización en el dispatcher así también como en
  214. los controladores creados por el usuario. En caso de no encontrar
  215. ninguna concordancia, se comprobará la siguiente ruta en la cadena.
  216. </para>
  217. <para>
  218. Si necesita determinar en qué ruta se encontró una concordancia,
  219. puede usar el método <methodname>getCurrentRouteName()</methodname>, que devolverá
  220. el identificador usado cuando registró la ruta con el router.
  221. Si quiere el objeto de la ruta actual, puede usar
  222. <methodname>getCurrentRoute()</methodname>.
  223. </para>
  224. <note>
  225. <title>Matching Inverso</title>
  226. <para>
  227. Las rutas están equiparadas en orden inverso para asegurarse
  228. que las rutas más genéricas se definan primero.
  229. </para>
  230. </note>
  231. <note>
  232. <title>Valores Retornados</title>
  233. <para>
  234. Los valores retornados del routing provienen de parámetros <acronym>URL</acronym>
  235. o de rutas definidas por defecto por el usuario.
  236. Estas variables son accesibles posteriormente a través de los métodos
  237. <methodname>Zend_Controller_Request::getParam()</methodname> o
  238. <methodname>Zend_Controller_Action::_getParam()</methodname>.
  239. </para>
  240. </note>
  241. <para>
  242. Hay tres variables que pueden utilizarse en las rutas - 'module',
  243. 'controller' y 'action'. Estas variables especiales son utilizados por
  244. <classname>Zend_Controller_Dispatcher</classname> para encontrar un
  245. controlador y una acción para hacer el dispatch.
  246. </para>
  247. <note>
  248. <title>Variables Especiales</title>
  249. <para>
  250. Los nombres de estas variables especiales pueden ser diferentes
  251. si elige alterar los valores por defecto en
  252. <classname>Zend_Controller_Request_Http</classname> mediante los
  253. métodos
  254. <methodname>setControllerKey</methodname> y <methodname>setActionKey</methodname>.
  255. </para>
  256. </note>
  257. </sect2>
  258. <sect2 id="zend.controller.router.default-routes">
  259. <title>Routes por Defecto</title>
  260. <para>
  261. <classname>Zend_Controller_Router_Rewrite</classname> viene
  262. preconfigurado con una ruta por defecto, que se comparará con <acronym>URI</acronym>s
  263. en la forma de <methodname>controller/action</methodname>.
  264. Además, se puede especificar un nombre de módulo como primer
  265. elemento del path, permitiendo <acronym>URI</acronym>s de la forma
  266. <filename>module/controller/action</filename>. Por último, también coincidrá
  267. con cualquier parámetro adicional agregado a la <acronym>URI</acronym> por defecto -
  268. <filename>controller/action/var1/value1/var2/value2</filename>.
  269. </para>
  270. <para>
  271. Algunos ejemplos de cómo están equiparadas las rutas:
  272. </para>
  273. <programlisting language="php"><![CDATA[
  274. // Asumiendo lo siguiente:
  275. $ctrl->setControllerDirectory(
  276. array(
  277. 'default' => '/path/to/default/controllers',
  278. 'news' => '/path/to/news/controllers',
  279. 'blog' => '/path/to/blog/controllers'
  280. )
  281. );
  282. Módulo únicamente:
  283. http://example/news
  284. module == news
  285. Modulo inválido mapea al nombre del controlador:
  286. http://example/foo
  287. controller == foo
  288. Módulo + controlador:
  289. http://example/blog/archive
  290. module == blog
  291. controller == archive
  292. Módulo + controlador + accción:
  293. http://example/blog/archive/list
  294. module == blog
  295. controller == archive
  296. action == list
  297. Módulo + controlador + accción + parámetros:
  298. http://example/blog/archive/list/sort/alpha/date/desc
  299. module == blog
  300. controller == archive
  301. action == list
  302. sort == alpha
  303. date == desc
  304. ]]></programlisting>
  305. <para>
  306. La ruta por defecto es simplemente un objeto
  307. <classname>Zend_Controller_Router_Route_Module</classname>
  308. almacenado bajo el nombre de (index) por 'default' en RewriteRouter.
  309. Está generado más o menos así:
  310. </para>
  311. <programlisting language="php"><![CDATA[
  312. $compat = new Zend_Controller_Router_Route_Module(array(),
  313. $dispatcher,
  314. $request);
  315. $this->addRoute('default', $compat);
  316. ]]></programlisting>
  317. <para>
  318. Si no quiere esta ruta en particular en su esquema por defecto de
  319. routing, podrá anularla creando su propia ruta por 'defecto'
  320. (es decir, almacenar bajo el nombre de 'default') o eliminarla por
  321. completo usando <methodname>removeDefaultRoutes()</methodname>:
  322. </para>
  323. <programlisting language="php"><![CDATA[
  324. // Eliminar cualquier ruta por defecto
  325. $router->removeDefaultRoutes();
  326. ]]></programlisting>
  327. </sect2>
  328. <sect2 id="zend.controller.router.rewritebase">
  329. <title>URL Base y Subdirectorios</title>
  330. <para>
  331. El router rewrite puede ser utilizado en subdirectorios (por
  332. ejemplo <filename>http://domain.com/~user/application-root/</filename>)
  333. en cuyo caso la <acronym>URL</acronym> base de la aplicación
  334. (<filename>/user/application-root</filename>) debe ser detectada
  335. automáticamente por <classname>Zend_Controller_Request_Http</classname>
  336. y usada en consecuencia.
  337. </para>
  338. <para>
  339. Si la <acronym>URL</acronym> base se detecta incorrectamente se la puede anular con su
  340. propio path de base usando
  341. <classname>Zend_Controller_Request_Http</classname> y llamando al
  342. método <methodname>setBaseUrl()</methodname> (ver <xref
  343. linkend="zend.controller.request.http.baseurl" />):
  344. </para>
  345. <programlisting language="php"><![CDATA[
  346. $request->setBaseUrl('/~user/application-root/');
  347. ]]></programlisting>
  348. </sect2>
  349. <sect2 id="zend.controller.router.global.parameters">
  350. <title>Parámetros Globales</title>
  351. <para>
  352. Puede establecer los parámetros globales en un router que se
  353. proporcionan automáticamente a una ruta cuando se ensamblasn mediante
  354. <methodname>setGlobalParam</methodname>. Si se establece un parámetro global
  355. pero también se lo entrega directamente al método de ensamblaje,
  356. el parámetro del usuario sobreescribe al parámetro global.
  357. Puede establecer un parámetro global esta forma:
  358. </para>
  359. <programlisting language="php"><![CDATA[
  360. $router->setGlobalParam('lang', 'en');
  361. ]]></programlisting>
  362. </sect2>
  363. <sect2 id="zend.controller.router.routes">
  364. <title>Tipos de Route</title>
  365. <xi:include href="Zend_Controller-Router-Route.xml" />
  366. <xi:include href="Zend_Controller-Router-Route-Static.xml" />
  367. <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
  368. <xi:include href="Zend_Controller-Router-Route-Hostname.xml" />
  369. <xi:include href="Zend_Controller-Router-Route-Chain.xml" />
  370. </sect2>
  371. <sect2 id="zend.controller.router.add-config">
  372. <title>Usando <classname>Zend_Config</classname> con RewriteRouter</title>
  373. <para>
  374. A veces es más conveniente para actualizar un archivo de
  375. configuración con nuevas rutas que modificar el código.
  376. Esto es posible a través del método <methodname>addConfig()</methodname>.
  377. Básicamente, se crea una configuración compatible con
  378. <classname>Zend_Config</classname>.
  379. Y en su código lo lee y lo pasa a RewriteRouter.
  380. </para>
  381. <para>
  382. Como ejemplo, considere el siguiente archivo <acronym>INI</acronym>:
  383. </para>
  384. <programlisting language="php"><![CDATA[
  385. [production]
  386. routes.archive.route = "archive/:year/*"
  387. routes.archive.defaults.controller = archive
  388. routes.archive.defaults.action = show
  389. routes.archive.defaults.year = 2000
  390. routes.archive.reqs.year = "\d+"
  391. routes.news.type = "Zend_Controller_Router_Route_Static"
  392. routes.news.route = "news"
  393. routes.news.defaults.controller = "news"
  394. routes.news.defaults.action = "list"
  395. routes.archive.type = "Zend_Controller_Router_Route_Regex"
  396. routes.archive.route = "archive/(\d+)"
  397. routes.archive.defaults.controller = "archive"
  398. routes.archive.defaults.action = "show"
  399. routes.archive.map.1 = "year"
  400. ; O: routes.archive.map.year = 1
  401. ]]></programlisting>
  402. <para>
  403. Entonces el archivo <acronym>INI</acronym> puede ser leído por un objeto
  404. <classname>Zend_Config</classname> como sigue:
  405. </para>
  406. <programlisting language="php"><![CDATA[
  407. $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
  408. $router = new Zend_Controller_Router_Rewrite();
  409. $router->addConfig($config, 'routes');
  410. ]]></programlisting>
  411. <para>
  412. En el ejemplo de arriba, le decimos el router que utilice la
  413. sección 'routes' del archivo <acronym>INI</acronym> para utilizarlo en sus rutas.
  414. Cada clave de primer nivel en esa sección será utilizada para definir
  415. un nombre de ruta; el ejemplo anterior define las rutas 'archive' y
  416. 'news'. Entonces cada ruta requiere, como mínimo, una entrada a la
  417. 'ruta' y una o más entradas por 'default'; opcionalmente puede
  418. proporcionarse una o más 'reqs' (abreviación de 'required').
  419. Dicho todo esto, estos corresponden a los tres argumentos que se le
  420. suministran al objeto
  421. <classname>Zend_Controller_Router_Route_Interface</classname>.
  422. Puede utilizarse una clave opcional 'type' para especificar el
  423. tipo de clase de ruta a utilizar en esa ruta en particular;
  424. por defecto, usa
  425. <classname>Zend_Controller_Router_Route</classname>.
  426. En el ejemplo de arriba, la ruta 'news' está definida para usar
  427. <classname>Zend_Controller_Router_Route_Static</classname>.
  428. </para>
  429. </sect2>
  430. <sect2 id="zend.controller.router.subclassing">
  431. <title>Subclassing del Router</title>
  432. <para>
  433. El standard rewrite router debería proporcionarle más funcionalidad
  434. si la necesita; más a menudo, sólo necesitará crear un nuevo
  435. tipo de ruta a fin de ofrecer funcionalidades nuevas o modificadas
  436. sobre las tutas provistas.
  437. </para>
  438. <para>
  439. Dicho esto, en algún momento puede encontrarse a si mismo deseando
  440. usar un paradigma diferente de routing. La intefaz
  441. <classname>Zend_Controller_Router_Interface</classname> proporciona
  442. la información mínima necesaria para crear un router, y consiste en
  443. un único método.
  444. </para>
  445. <programlisting language="php"><![CDATA[
  446. interface Zend_Controller_Router_Interface
  447. {
  448. /**
  449. * @param Zend_Controller_Request_Abstract $request
  450. * @throws Zend_Controller_Router_Exception
  451. * @return Zend_Controller_Request_Abstract
  452. */
  453. public function route(Zend_Controller_Request_Abstract $request);
  454. }
  455. ]]></programlisting>
  456. <para>
  457. El routing sólo ocurre una vez: cuando la petición es recibida por
  458. primera vez en el sistema. El propósito del router es determinar el
  459. controlador, la acción, y los parámetros opcionales sobre la base
  460. del medio ambiente de la solicitud, y luego ajustarlos en la solicitud.
  461. El objeto solicitud se pasa entonces al dispatcher.
  462. Si no es posible trazar una ruta hacia un dispatch token,
  463. el router no debe hacer nada con el objeto solicitud.
  464. </para>
  465. </sect2>
  466. </sect1>
  467. <!--
  468. vim:se ts=4 sw=4 et:
  469. -->