El Router Standard
Introducción
Zend_Controller_Router_Rewrite Es el router
standard del Framework. Routing es el proceso de tomar la parte
final de una URI (la parte de la URI que viene después de la URL
base) y la descomposición en parámetros para determinar qué módulo,
qué controlador y acción de ese controlador debe recibir la solicitud.
Estos valores del módulo, controlador, acción y otros parámetros
están enpaquetados en un objeto
Zend_Controller_Request_Http el cual es
procesado luego por Zend_Controller_Dispatcher_Standard.
El routing ocurre sólo una vez: cuando se recibió inicialmente la
solicitud y antes del dispatch del primer controlador.
Zend_Controller_Router_Rewrite está diseñado
para permitir que una funcionalidad tipo mod_rewrite se pueda usar
en estructuras PHP puras. Se basa muy vagamente en el routing de
Ruby on Rails (RoR) y no requiere ningún conocimiento previo de
reescritura de la URL del webserver. Está diseñado para trabajar
con solo una regla mod_rewrite de Apache (one of):
o (preferido):
El router rewrite también puede utilizarse con el IIS webserver (versions <= 7.0) si Isapi_Rewrite
se ha instalado como una extensión Isapi con la siguiente
regla de reescribir:
IIS Isapi_Rewrite
Cuando se usa IIS, $_SERVER['REQUEST_URI'] puede
no existir, o establecerlo como un string vacío. En este caso,
Zend_Controller_Request_Http
intentará usar el valor de
$_SERVER['HTTP_X_REWRITE_URL']
establecido por la extensión Isapi_Rewrite.
IIS 7.0 introduce un módulo nativo de reescribir la URL, y puede ser
configurado como sigue:
]>
Si está usando Lighttpd, la siguiente regla de reescritura es válida:
"/index.php?$1",
".*\.(js|ico|gif|jpg|png|css|html)$" => "$0",
"" => "/index.php"
)
]]>
Usando un Router
Para utilizar adecuadamente el router de reescritura debe
instanciarlo, agregar algunas rutas definidas por el usuario y
luego inyectarlo en el controlador. El siguiente código ilustra el
procedimiento:
getRouter(); // returns a rewrite router by default
$router->addRoute(
'user',
new Zend_Controller_Router_Route('user/:username',
array('controller' => 'user',
'action' => 'info'))
);
]]>
Operación Básica del Rewrite Router
El corazón del RewriteRouter es la definición de la rutas definidas
por el usuario. Las rutas se agregan llamando al método addRoute
de RewriteRouter y pasándole una nueva instancia de una clase que
implementó a
Zend_Controller_Router_Route_Interface. Eg.:
addRoute('user',
new Zend_Controller_Router_Route('user/:username'));
]]>
El Rewrite Router viene con seis tipos básicos de rutas (uno de los
cuales es especial):
*
Las rutas pueden ser utilizadas numerosas veces para crear una cadena
o un esquema de aplicación de ruteo definido por el usuario.
Puede usar cualquier número de rutas en cualquier configuración,
con la excepción de la ruta del Módulo, la cual debe ser utilizada
una vez y probablemente como la ruta más genérica (es decir,
por defecto). Cada ruta se describe en mayor detalle más adelante.
El primer parámetro a addRoute es el nombre de la ruta.
Se utiliza como un manejador para sacar las rutas del router
(por ejemplo, con fines de generación de URL).
El segundo parámetro es la ruta misma.
El uso más común del nombre de ruta es por medio del
ayudante de url Zend_View:
url(array('username' => 'martel'), 'user') ?>">Martel
]]>
Que resultaría en la href: user/martel.
El routing es un simple proceso de iteración a través de todas las
rutas provistas y la equiparación de sus definiciones con la petición
actual de URI. Cuando se encuentra una concordancia, se devuelven
valores de variables desde la instancia Route y se inyecta en el
objeto Zend_Controller_Request
para su posterior utilización en el dispatcher así también como en
los controladores creados por el usuario. En caso de no encontrar
ninguna concordancia, se comprobará la siguiente ruta en la cadena.
Si necesita determinar en qué ruta se encontró una concordancia,
puede usar el método getCurrentRouteName(), que devolverá
el identificador usado cuando registró la ruta con el router.
Si quiere el objeto de la ruta actual, puede usar
getCurrentRoute().
Matching Inverso
Las rutas están equiparadas en orden inverso para asegurarse
que las rutas más genéricas se definan primero.
Valores Retornados
Los valores retornados del routing provienen de parámetros URL
o de rutas definidas por defecto por el usuario.
Estas variables son accesibles posteriormente a través de los métodos
Zend_Controller_Request::getParam() o
Zend_Controller_Action::_getParam().
Hay tres variables que pueden utilizarse en las rutas - 'module',
'controller' y 'action'. Estas variables especiales son utilizados por
Zend_Controller_Dispatcher para encontrar un
controlador y una acción para hacer el dispatch.
Variables Especiales
Los nombres de estas variables especiales pueden ser diferentes
si elige alterar los valores por defecto en
Zend_Controller_Request_Http mediante los
métodos
setControllerKey y setActionKey.
Routes por Defecto
Zend_Controller_Router_Rewrite viene
preconfigurado con una ruta por defecto, que se comparará con URIs
en la forma de controller/action.
Además, se puede especificar un nombre de módulo como primer
elemento del path, permitiendo URIs de la forma
module/controller/action. Por último, también coincidrá
con cualquier parámetro adicional agregado a la URI por defecto -
controller/action/var1/value1/var2/value2.
Algunos ejemplos de cómo están equiparadas las rutas:
setControllerDirectory(
array(
'default' => '/path/to/default/controllers',
'news' => '/path/to/news/controllers',
'blog' => '/path/to/blog/controllers'
)
);
Módulo únicamente:
http://example/news
module == news
Modulo inválido mapea al nombre del controlador:
http://example/foo
controller == foo
Módulo + controlador:
http://example/blog/archive
module == blog
controller == archive
Módulo + controlador + accción:
http://example/blog/archive/list
module == blog
controller == archive
action == list
Módulo + controlador + accción + parámetros:
http://example/blog/archive/list/sort/alpha/date/desc
module == blog
controller == archive
action == list
sort == alpha
date == desc
]]>
La ruta por defecto es simplemente un objeto
Zend_Controller_Router_Route_Module
almacenado bajo el nombre de (index) por 'default' en RewriteRouter.
Está generado más o menos así:
addRoute('default', $compat);
]]>
Si no quiere esta ruta en particular en su esquema por defecto de
routing, podrá anularla creando su propia ruta por 'defecto'
(es decir, almacenar bajo el nombre de 'default') o eliminarla por
completo usando removeDefaultRoutes():
removeDefaultRoutes();
]]>
URL Base y Subdirectorios
El router rewrite puede ser utilizado en subdirectorios (por
ejemplo http://domain.com/~user/application-root/)
en cuyo caso la URL base de la aplicación
(/~user/application-root) debe ser detectada
automáticamente por Zend_Controller_Request_Http
y usada en consecuencia.
Si la URL base se detecta incorrectamente se la puede anular con su
propio path de base usando
Zend_Controller_Request_Http y llamando al
método setBaseUrl() (ver ):
setBaseUrl('/~user/application-root/');
]]>
Parámetros Globales
Puede establecer los parámetros globales en un router que se
proporcionan automáticamente a una ruta cuando se ensamblasn mediante
setGlobalParam. Si se establece un parámetro global
pero también se lo entrega directamente al método de ensamblaje,
el parámetro del usuario sobreescribe al parámetro global.
Puede establecer un parámetro global esta forma:
setGlobalParam('lang', 'en');
]]>
Tipos de Route
Usando Zend_Config con RewriteRouter
A veces es más conveniente para actualizar un archivo de
configuración con nuevas rutas que modificar el código.
Esto es posible a través del método addConfig().
Básicamente, se crea una configuración compatible con
Zend_Config.
Y en su código lo lee y lo pasa a RewriteRouter.
Como ejemplo, considere el siguiente archivo INI:
Entonces el archivo INI puede ser leído por un objeto
Zend_Config como sigue:
addConfig($config, 'routes');
]]>
En el ejemplo de arriba, le decimos el router que utilice la
sección 'routes' del archivo INI para utilizarlo en sus rutas.
Cada clave de primer nivel en esa sección será utilizada para definir
un nombre de ruta; el ejemplo anterior define las rutas 'archive' y
'news'. Entonces cada ruta requiere, como mínimo, una entrada a la
'ruta' y una o más entradas por 'default'; opcionalmente puede
proporcionarse una o más 'reqs' (abreviación de 'required').
Dicho todo esto, estos corresponden a los tres argumentos que se le
suministran al objeto
Zend_Controller_Router_Route_Interface.
Puede utilizarse una clave opcional 'type' para especificar el
tipo de clase de ruta a utilizar en esa ruta en particular;
por defecto, usa
Zend_Controller_Router_Route.
En el ejemplo de arriba, la ruta 'news' está definida para usar
Zend_Controller_Router_Route_Static.
Subclassing del Router
El standard rewrite router debería proporcionarle más funcionalidad
si la necesita; más a menudo, sólo necesitará crear un nuevo
tipo de ruta a fin de ofrecer funcionalidades nuevas o modificadas
sobre las tutas provistas.
Dicho esto, en algún momento puede encontrarse a si mismo deseando
usar un paradigma diferente de routing. La intefaz
Zend_Controller_Router_Interface proporciona
la información mínima necesaria para crear un router, y consiste en
un único método.
El routing sólo ocurre una vez: cuando la petición es recibida por
primera vez en el sistema. El propósito del router es determinar el
controlador, la acción, y los parámetros opcionales sobre la base
del medio ambiente de la solicitud, y luego ajustarlos en la solicitud.
El objeto solicitud se pasa entonces al dispatcher.
Si no es posible trazar una ruta hacia un dispatch token,
el router no debe hacer nada con el objeto solicitud.