El Router StandardIntroducciónZend_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):
Zend_Controller_Router_Route
Zend_Controller_Router_Route_Static
Zend_Controller_Router_Route_Regex
Zend_Controller_Router_Route_Hostname
Zend_Controller_Router_Route_Chain
Zend_Controller_Router_Rewrite
*
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 DefectoZend_Controller_Router_Rewrite
viene
preconfigurado con una ruta por defecto, que se comparará con
URI
s
en la forma de
controller/action
.
Además, se puede especificar un nombre de módulo como primer
elemento del path,
permitiendo
URI
s 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.