Zend_Controller_Router_Route_Regex
Además de los tipos de ruta estáticos y por defecto, también está
disponible el tipo de ruta Expresión Regular. Esta ruta ofrece más
potencia y flexibilidad que los otros, pero a costa de un ligero aumento
en la complejidad. Al mismo tiempo, debería ser más rápido que la
standard Route.
Al igual que la standard Route, esta ruta tiene que ser inicializada
con una definición de ruta y algunos valores predeterminados. Vamos a
crear un archivo ruta como un ejemplo, similar al previamente definido,
sólo que esta vez usaremos la ruta Regex:
'archive',
'action' => 'show'
)
);
$router->addRoute('archive', $route);
]]>
Cada sub-patrón regex definido será inyectado al objeto solicitud.
Con nuestro ejemplo anterior, después de un matching exitoso
http://domain.com/archive/2006, el valor
resultante del array puede verse como:
'2006',
'controller' => 'archive',
'action' => 'show'
);
]]>
Las barras de comienzo y final están recortadas de la
URL en el Router antes de una concordancia.
Como resultado, coincidendo con la URL
http://domain.com/foo/bar/, involucraría al
regex de foo/bar, y no a
/foo/bar.
Las anclas de comienzo y fin de línea ('^' y '$',
respectivamente) son automáticamente antepuestas y pospuestas a
todas las expresiones. Así, no debe usar éstas en sus expresiones
regulares, y debe coincidir con el string completo.
Esta clase de ruta usa el carácter #
como un delimitador. Esto significa que necesitará caracteres hash
('#') para escapar pero no barras ('/') en sus definiciones de ruta.
Dado que el carácter '#' (llamado ancla) es raramente pasado al
webserver, será muy rara la necesidad de utilizar ese carácter en su
regex.
Puede obtener el contenido de los sub-patrones definidos por la forma
habitual:
getRequest();
$year = $request->getParam(1); // $year = '2006';
}
]]>
Tenga en cuenta que la clave es un entero (1) en lugar de un
string ('1').
Sin embargo, esta ruta no funciona exactamente igual que su
contraparte standard route dado que el valor por defecto para 'year'
todavía no se ha establecido. Y lo que puede ser no tan evidente es que
tendremos un problema con una barra final incluso si declaramos por
defecto el año y hacemos opcional al sub-patrón. La solución es hacer
que toda la parte del año sea opcional junto con la barra pero capturar
solo la parte numérica:
'2006',
'controller' => 'archive',
'action' => 'show'
)
);
$router->addRoute('archive', $route);
]]>
Ahora, ocupemósnos del problema que probablemente haya notado.
Utilizar claves basadas en enteros para los parámetros no es una
solución fácilmente manejable y puede ser potencialmente problemática a
largo plazo. Y aquí es donde entra el tercer parámetro. Este parámetro
es un array asociativo que representa un mapa de sub-patrones regex a
nombres de clave de parámetros. Trabajemos en nuestro ejemplo más fácil:
'archive',
'action' => 'show'
),
array(
1 => 'year'
)
);
$router->addRoute('archive', $route);
]]>
Esto resultaraá en los siguientes valores inyectados a la solicitud:
'2006',
'controller' => 'archive',
'action' => 'show'
);
]]>
El mapa puede ser definido en cualquier dirección para hacer que
funcione en cualquier ambiente. Las claves pueden contener nombres de
variables o índices de sub-patrones:
'year')
);
// O
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array( ... ),
array('year' => 1)
);
]]>
Las claves de los sub-patrones deben respresentarse por enteros.
Observe que el índice numérico en los valores del Request ahora han
desaparecido y en su lugar se muestra una variable nombrada. Por
supuesto que puede mezclar variables nombradas y numéricas si lo desea:
1)
);
]]>
Lo que resultará en una mezcla de valores disponibles en la
solicitud. Como ejemplo, la URL
http://domain.com/archive/2006/page/10 resultará
con los siguientes valores:
'2006',
2 => 10,
'controller' => 'archive',
'action' => 'show'
);
]]>
Dado que los patrones regex no pueden invertirse fácilmente, tendrá
que preparar una URL inversa si desea usar un
ayudante de URL o incluso un método de ensamble de
esta clase. Este path inverso está representado por un string parseable
por sprintf() y se define como el cuarto parámetro del constructor:
1),
'archive/%s'
);
]]>
Todo esto es algo que ya fue posible de hacer por medio de un objeto
de ruta estandard, por lo tanto podría preguntarese: ¿cuál es la ventaja
de utilizar la ruta Regex?. Principalmente, le permite describir
cualquier tipo de URL sin restricción alguna.
Imagínese que tiene un blog y desea crear URLs como:
http://domain.com/blog/archive/01-Using_the_Regex_Router.html,
y que tiene que descomponer el último elemento del path
01-Using_the_Regex_Router.html, en un ID de
artículo y en el título o descripción del artículo; esto no es posible con
el standard route. Con la ruta Regex, puede hacer algo como la siguiente
solución:
'blog',
'action' => 'view'
),
array(
1 => 'id',
2 => 'description'
),
'blog/archive/%d-%s.html'
);
$router->addRoute('blogArchive', $route);
]]>
Como puede ver, esto añade una enorme cantidad de flexibilidad por
encima del standard route.