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/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.