Zend_Controller-Router.xml 23 KB

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