Zend_Controller-Router-Route-Regex.xml 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 24249 -->
  3. <!-- Reviewed: no -->
  4. <sect3 id="zend.controller.router.routes.regex">
  5. <title>Zend_Controller_Router_Route_Regex</title>
  6. <para>Además de los tipos de ruta estáticos y por defecto, también está
  7. disponible el tipo de
  8. ruta Expresión Regular. Esta ruta ofrece más
  9. potencia y flexibilidad que los otros, pero a
  10. costa de un ligero aumento
  11. en la complejidad. Al mismo tiempo, debería ser más rápido que la
  12. standard Route.</para>
  13. <para>Al igual que la standard Route, esta ruta tiene que ser inicializada
  14. con una definición de
  15. ruta y algunos valores predeterminados. Vamos a
  16. crear un archivo ruta como un ejemplo,
  17. similar al previamente definido,
  18. sólo que esta vez usaremos la ruta Regex:</para>
  19. <programlisting language="php"><![CDATA[
  20. $route = new Zend_Controller_Router_Route_Regex(
  21. 'archive/(\d+)',
  22. array(
  23. 'controller' => 'archive',
  24. 'action' => 'show'
  25. )
  26. );
  27. $router->addRoute('archive', $route);
  28. ]]></programlisting>
  29. <para>
  30. Cada sub-patrón regex definido será inyectado al objeto solicitud.
  31. Con nuestro ejemplo
  32. anterior, después de un matching exitoso
  33. <filename>http://domain.com/archive/2006</filename>
  34. , el valor
  35. resultante del array puede verse como:
  36. </para>
  37. <programlisting language="php"><![CDATA[
  38. $values = array(
  39. 1 => '2006',
  40. 'controller' => 'archive',
  41. 'action' => 'show'
  42. );
  43. ]]></programlisting>
  44. <note>
  45. <para>
  46. Las barras de comienzo y final están recortadas de la
  47. <acronym>URL</acronym>
  48. en el Router antes de una concordancia.
  49. Como resultado, coincidendo con la
  50. <acronym>URL</acronym>
  51. <filename>http://domain.com/foo/bar/</filename>
  52. , involucraría al
  53. regex de
  54. <filename>foo/bar</filename>
  55. , y no a
  56. <filename>/foo/bar</filename>
  57. .
  58. </para>
  59. </note>
  60. <note>
  61. <para>Las anclas de comienzo y fin de línea ('^' y '$',
  62. respectivamente) son automáticamente
  63. antepuestas y pospuestas a
  64. todas las expresiones. Así, no debe usar éstas en sus
  65. expresiones
  66. regulares, y debe coincidir con el string completo.</para>
  67. </note>
  68. <note>
  69. <para>
  70. Esta clase de ruta usa el carácter
  71. <emphasis>#</emphasis>
  72. como un delimitador. Esto significa que necesitará caracteres hash
  73. ('#') para escapar
  74. pero no barras ('/') en sus definiciones de ruta.
  75. Dado que el carácter '#' (llamado
  76. ancla) es raramente pasado al
  77. webserver, será muy rara la necesidad de utilizar ese
  78. carácter en su
  79. regex.
  80. </para>
  81. </note>
  82. <para>Puede obtener el contenido de los sub-patrones definidos por la forma
  83. habitual:</para>
  84. <programlisting language="php"><![CDATA[
  85. public function showAction()
  86. {
  87. $request = $this->getRequest();
  88. $year = $request->getParam(1); // $year = '2006';
  89. }
  90. ]]></programlisting>
  91. <note>
  92. <para>Tenga en cuenta que la clave es un entero (1) en lugar de un
  93. string ('1').</para>
  94. </note>
  95. <para>Sin embargo, esta ruta no funciona exactamente igual que su
  96. contraparte standard route dado
  97. que el valor por defecto para 'year'
  98. todavía no se ha establecido. Y lo que puede ser no tan
  99. evidente es que
  100. tendremos un problema con una barra final incluso si declaramos por
  101. defecto el
  102. año y hacemos opcional al sub-patrón. La solución es hacer
  103. que toda la parte del año sea
  104. opcional junto con la barra pero capturar
  105. solo la parte numérica:</para>
  106. <programlisting language="php"><![CDATA[
  107. $route = new Zend_Controller_Router_Route_Regex(
  108. 'archive(?:/(\d+))?',
  109. array(
  110. 1 => '2006',
  111. 'controller' => 'archive',
  112. 'action' => 'show'
  113. )
  114. );
  115. $router->addRoute('archive', $route);
  116. ]]></programlisting>
  117. <para>Ahora, ocupemósnos del problema que probablemente haya notado.
  118. Utilizar claves basadas en
  119. enteros para los parámetros no es una
  120. solución fácilmente manejable y puede ser
  121. potencialmente problemática a
  122. largo plazo. Y aquí es donde entra el tercer parámetro. Este
  123. parámetro
  124. es un array asociativo que representa un mapa de sub-patrones regex a
  125. nombres de
  126. clave de parámetros. Trabajemos en nuestro ejemplo más fácil:</para>
  127. <programlisting language="php"><![CDATA[
  128. $route = new Zend_Controller_Router_Route_Regex(
  129. 'archive/(\d+)',
  130. array(
  131. 'controller' => 'archive',
  132. 'action' => 'show'
  133. ),
  134. array(
  135. 1 => 'year'
  136. )
  137. );
  138. $router->addRoute('archive', $route);
  139. ]]></programlisting>
  140. <para>Esto resultaraá en los siguientes valores inyectados a la solicitud:</para>
  141. <programlisting language="php"><![CDATA[
  142. $values = array(
  143. 'year' => '2006',
  144. 'controller' => 'archive',
  145. 'action' => 'show'
  146. );
  147. ]]></programlisting>
  148. <para>El mapa puede ser definido en cualquier dirección para hacer que
  149. funcione en cualquier
  150. ambiente. Las claves pueden contener nombres de
  151. variables o índices de sub-patrones:</para>
  152. <programlisting language="php"><![CDATA[
  153. $route = new Zend_Controller_Router_Route_Regex(
  154. 'archive/(\d+)',
  155. array( ... ),
  156. array(1 => 'year')
  157. );
  158. // O
  159. $route = new Zend_Controller_Router_Route_Regex(
  160. 'archive/(\d+)',
  161. array( ... ),
  162. array('year' => 1)
  163. );
  164. ]]></programlisting>
  165. <note>
  166. <para>Las claves de los sub-patrones deben respresentarse por enteros.
  167. </para>
  168. </note>
  169. <para>Observe que el índice numérico en los valores del Request ahora han
  170. desaparecido y en su
  171. lugar se muestra una variable nombrada. Por
  172. supuesto que puede mezclar variables nombradas y
  173. numéricas si lo desea:</para>
  174. <programlisting language="php"><![CDATA[
  175. $route = new Zend_Controller_Router_Route_Regex(
  176. 'archive/(\d+)/page/(\d+)',
  177. array( ... ),
  178. array('year' => 1)
  179. );
  180. ]]></programlisting>
  181. <para>
  182. Lo que resultará en una mezcla de valores disponibles en la
  183. solicitud. Como ejemplo, la
  184. <acronym>URL</acronym>
  185. <filename>http://domain.com/archive/2006/page/10</filename>
  186. resultará
  187. con los siguientes valores:
  188. </para>
  189. <programlisting language="php"><![CDATA[
  190. $values = array(
  191. 'year' => '2006',
  192. 2 => 10,
  193. 'controller' => 'archive',
  194. 'action' => 'show'
  195. );
  196. ]]></programlisting>
  197. <para>
  198. Dado que los patrones regex no pueden invertirse fácilmente, tendrá
  199. que preparar una
  200. <acronym>URL</acronym>
  201. inversa si desea usar un
  202. ayudante de
  203. <acronym>URL</acronym>
  204. o incluso un método de ensamble de
  205. esta clase. Este path inverso está representado por un
  206. string parseable
  207. por
  208. <methodname>sprintf()</methodname>
  209. y se define como el cuarto parámetro del constructor:
  210. </para>
  211. <programlisting language="php"><![CDATA[
  212. $route = new Zend_Controller_Router_Route_Regex(
  213. 'archive/(\d+)',
  214. array( ... ),
  215. array('year' => 1),
  216. 'archive/%s'
  217. );
  218. ]]></programlisting>
  219. <para>
  220. Todo esto es algo que ya fue posible de hacer por medio de un objeto
  221. de ruta estandard, por
  222. lo tanto podría preguntarese: ¿cuál es la ventaja
  223. de utilizar la ruta Regex?. Principalmente,
  224. le permite describir
  225. cualquier tipo de
  226. <acronym>URL</acronym>
  227. sin restricción alguna.
  228. Imagínese que tiene un blog y desea crear URLs como:
  229. <filename>http://domain.com/blog/archive/01-Using_the_Regex_Router.html</filename>
  230. ,
  231. y que tiene que descomponer el último elemento del path
  232. <filename>01-Using_the_Regex_Router.html</filename>
  233. , en un ID de
  234. artículo y en el título o descripción del artículo; esto no es posible con
  235. el
  236. standard route. Con la ruta Regex, puede hacer algo como la siguiente
  237. solución:
  238. </para>
  239. <programlisting language="php"><![CDATA[
  240. $route = new Zend_Controller_Router_Route_Regex(
  241. 'blog/archive/(\d+)-(.+)\.html',
  242. array(
  243. 'controller' => 'blog',
  244. 'action' => 'view'
  245. ),
  246. array(
  247. 1 => 'id',
  248. 2 => 'description'
  249. ),
  250. 'blog/archive/%d-%s.html'
  251. );
  252. $router->addRoute('blogArchive', $route);
  253. ]]></programlisting>
  254. <para>Como puede ver, esto añade una enorme cantidad de flexibilidad por
  255. encima del standard
  256. route.</para>
  257. </sect3>