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.