| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.controller.router" xmlns:xi="http://www.w3.org/2001/XInclude">
- <title>El Router Standard</title>
- <sect2 id="zend.controller.router.introduction">
- <title>Introducción</title>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> Es el router
- standard del Framework. Routing es el proceso de tomar la parte
- final de una <acronym>URI</acronym> (la parte de la
- <acronym>URI</acronym> que viene después de la
- <acronym>URL</acronym> 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 <classname>Zend_Controller_Request_Http</classname> el cual
- es procesado luego por
- <classname>Zend_Controller_Dispatcher_Standard</classname> . El
- routing ocurre sólo una vez: cuando se recibió inicialmente la
- solicitud y antes del dispatch del primer controlador. </para>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> está diseñado
- para permitir que una funcionalidad tipo mod_rewrite se pueda usar
- en estructuras <acronym>PHP</acronym> puras. Se basa muy vagamente
- en el routing de Ruby on Rails (RoR) y no requiere ningún
- conocimiento previo de reescritura de la <acronym>URL</acronym> del
- webserver. Está diseñado para trabajar con solo una regla
- mod_rewrite de Apache (one of): </para>
- <programlisting language="php"><![CDATA[
- RewriteEngine on
- RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
- ]]></programlisting>
- <para> o (preferido): </para>
- <programlisting language="php"><![CDATA[
- RewriteEngine On
- RewriteCond %{REQUEST_FILENAME} -s [OR]
- RewriteCond %{REQUEST_FILENAME} -l [OR]
- RewriteCond %{REQUEST_FILENAME} -d
- RewriteRule ^.*$ - [NC,L]
- RewriteRule ^.*$ index.php [NC,L]
- ]]></programlisting>
- <para> El router rewrite también puede utilizarse con el
- <acronym>IIS</acronym> webserver (versions <= 7.0) si
- <ulink url="http://www.isapirewrite.com">Isapi_Rewrite</ulink>
- se ha instalado como una extensión Isapi con la siguiente regla de
- reescribir: </para>
- <programlisting language="php"><![CDATA[
- RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css|html)$)[\w\%]*$)? /index.php [I]
- ]]></programlisting>
- <note>
- <title>IIS Isapi_Rewrite</title>
- <para> Cuando se usa <acronym>IIS</acronym> ,
- <varname>$_SERVER['REQUEST_URI']</varname> puede no existir,
- o establecerlo como un string vacío. En este caso,
- <classname>Zend_Controller_Request_Http</classname>
- intentará usar el valor de
- <varname>$_SERVER['HTTP_X_REWRITE_URL']</varname>
- establecido por la extensión Isapi_Rewrite. </para>
- </note>
- <para> IIS 7.0 introduce un módulo nativo de reescribir la URL, y puede
- ser configurado como sigue: </para>
- <programlisting language="xml"><![CDATA[
- <?xml version="1.0" encoding="UTF-8"?>
- <configuration>
- <system.webServer>
- <rewrite>
- <rules>
- <rule name="Imported Rule 1" stopProcessing="true">
- <match url="^.*$" />
- <conditions logicalGrouping="MatchAny">
- <add input="{REQUEST_FILENAME}"
- matchType="IsFile" pattern=""
- ignoreCase="false" />
- <add input="{REQUEST_FILENAME}"
- matchType="IsDirectory"
- pattern="" ignoreCase="false" />
- </conditions>
- <action type="None" />
- </rule>
- <rule name="Imported Rule 2" stopProcessing="true">
- <match url="^.*$" />
- <action type="Rewrite" url="index.php" />
- </rule>
- </rules>
- </rewrite>
- </system.webServer>
- </configuration>]></programlisting>
- <para>
- Si está usando Lighttpd, la siguiente regla de reescritura es válida:
- </para>
- <programlisting language="lighttpd"><![CDATA[
- url.rewrite-once = (
- ".*\?(.*)$" => "/index.php?$1",
- ".*\.(js|ico|gif|jpg|png|css|html)$" => "$0",
- "" => "/index.php"
- )
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.usage">
- <title>Usando un Router</title>
- <para> 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: </para>
- <programlisting language="php"><![CDATA[
- // Crear un router
- $router = $ctrl->getRouter(); // returns a rewrite router by default
- $router->addRoute(
- 'user',
- new Zend_Controller_Router_Route('user/:username',
- array('controller' => 'user',
- 'action' => 'info'))
- );
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.basic">
- <title>Operación Básica del Rewrite Router</title>
- <para> 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
- <classname>Zend_Controller_Router_Route_Interface</classname> .
- Eg.: </para>
- <programlisting language="php"><![CDATA[
- $router->addRoute('user',
- new Zend_Controller_Router_Route('user/:username'));
- ]]></programlisting>
- <para> El Rewrite Router viene con seis tipos básicos de rutas (uno de
- los cuales es especial): </para>
- <itemizedlist mark="opencircle">
- <listitem>
- <para>
- <link linkend="zend.controller.router.routes.standard"
- >Zend_Controller_Router_Route</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link linkend="zend.controller.router.routes.static"
- >Zend_Controller_Router_Route_Static</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link linkend="zend.controller.router.routes.regex"
- >Zend_Controller_Router_Route_Regex</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link linkend="zend.controller.router.routes.hostname"
- >Zend_Controller_Router_Route_Hostname</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link linkend="zend.controller.router.routes.chain"
- >Zend_Controller_Router_Route_Chain</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link linkend="zend.controller.router.default-routes"
- >Zend_Controller_Router_Rewrite</link> * </para>
- </listitem>
- </itemizedlist>
- <para> 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. </para>
- <para> 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 <acronym>URL</acronym> ). El
- segundo parámetro es la ruta misma. </para>
- <note>
- <para> El uso más común del nombre de ruta es por medio del ayudante
- de <acronym>URL</acronym>
- <classname>Zend_View</classname> : </para>
- <programlisting language="php"><![CDATA[
- <a href=
- "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
- ]]></programlisting>
- <para> Que resultaría en la href: <filename>user/martel</filename> .
- </para>
- </note>
- <para> 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 <acronym>URI</acronym> . Cuando se encuentra una
- concordancia, se devuelven valores de variables desde la instancia
- Route y se inyecta en el objeto
- <classname>Zend_Controller_Request</classname> 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. </para>
- <para> Si necesita determinar en qué ruta se encontró una concordancia,
- puede usar el método <methodname>getCurrentRouteName()</methodname>
- , que devolverá el identificador usado cuando registró la ruta con
- el router. Si quiere el objeto de la ruta actual, puede usar
- <methodname>getCurrentRoute()</methodname> . </para>
- <note>
- <title>Matching Inverso</title>
- <para> Las rutas están equiparadas en orden inverso para asegurarse
- que las rutas más genéricas se definan primero. </para>
- </note>
- <note>
- <title>Valores Retornados</title>
- <para> Los valores retornados del routing provienen de parámetros
- <acronym>URL</acronym> o de rutas definidas por defecto por
- el usuario. Estas variables son accesibles posteriormente a
- través de los métodos
- <methodname>Zend_Controller_Request::getParam()</methodname>
- o <methodname>Zend_Controller_Action::_getParam()</methodname> .
- </para>
- </note>
- <para> Hay tres variables que pueden utilizarse en las rutas - 'module',
- 'controller' y 'action'. Estas variables especiales son utilizados
- por <classname>Zend_Controller_Dispatcher</classname> para encontrar
- un controlador y una acción para hacer el dispatch. </para>
- <note>
- <title>Variables Especiales</title>
- <para> Los nombres de estas variables especiales pueden ser
- diferentes si elige alterar los valores por defecto en
- <classname>Zend_Controller_Request_Http</classname> mediante
- los métodos <methodname>setControllerKey()</methodname> y
- <methodname>setActionKey()</methodname> . </para>
- </note>
- </sect2>
- <sect2 id="zend.controller.router.default-routes">
- <title>Routes por Defecto</title>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> viene
- preconfigurado con una ruta por defecto, que se comparará con
- <acronym>URI</acronym> s en la forma de
- <filename>controller/action</filename> . Además, se puede
- especificar un nombre de módulo como primer elemento del path,
- permitiendo <acronym>URI</acronym> s de la forma
- <filename>module/controller/action</filename> . Por último,
- también coincidrá con cualquier parámetro adicional agregado a la
- <acronym>URI</acronym> por defecto -
- <filename>controller/action/var1/value1/var2/value2</filename> . </para>
- <para> Algunos ejemplos de cómo están equiparadas las rutas: </para>
- <programlisting language="php"><![CDATA[
- // Asumiendo lo siguiente:
- $ctrl->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
- ]]></programlisting>
- <para> La ruta por defecto es simplemente un objeto
- <classname>Zend_Controller_Router_Route_Module</classname>
- almacenado bajo el nombre de (index) por 'default' en RewriteRouter.
- Está generado más o menos así: </para>
- <programlisting language="php"><![CDATA[
- $compat = new Zend_Controller_Router_Route_Module(array(),
- $dispatcher,
- $request);
- $this->addRoute('default', $compat);
- ]]></programlisting>
- <para> 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 <methodname>removeDefaultRoutes()</methodname> : </para>
- <programlisting language="php"><![CDATA[
- // Eliminar cualquier ruta por defecto
- $router->removeDefaultRoutes();
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.rewritebase">
- <title>URL Base y Subdirectorios</title>
- <para> El router rewrite puede ser utilizado en subdirectorios (por
- ejemplo
- <filename>http://domain.com/~user/application-root/</filename> )
- en cuyo caso la <acronym>URL</acronym> base de la aplicación (
- <filename>/user/application-root</filename> ) debe ser detectada
- automáticamente por
- <classname>Zend_Controller_Request_Http</classname> y usada en
- consecuencia. </para>
- <para> Si la <acronym>URL</acronym> base se detecta incorrectamente se
- la puede anular con su propio path de base usando
- <classname>Zend_Controller_Request_Http</classname> y llamando
- al método <methodname>setBaseUrl()</methodname> (ver <xref
- linkend="zend.controller.request.http.baseurl"/> ): </para>
- <programlisting language="php"><![CDATA[
- $request->setBaseUrl('/~user/application-root/');
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.global.parameters">
- <title>Parámetros Globales</title>
- <para> Puede establecer los parámetros globales en un router que se
- proporcionan automáticamente a una ruta cuando se ensamblasn
- mediante <methodname>setGlobalParam()</methodname> . 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: </para>
- <programlisting language="php"><![CDATA[
- $router->setGlobalParam('lang', 'en');
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.routes">
- <title>Tipos de Route</title>
- <xi:include href="Zend_Controller-Router-Route.xml"/>
- <xi:include href="Zend_Controller-Router-Route-Static.xml"/>
- <xi:include href="Zend_Controller-Router-Route-Regex.xml"/>
- <xi:include href="Zend_Controller-Router-Route-Hostname.xml"/>
- <xi:include href="Zend_Controller-Router-Route-Chain.xml"/>
- </sect2>
- <sect2 id="zend.controller.router.add-config">
- <title> Usando Zend_Config con RewriteRouter </title>
- <para> 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 <methodname>addConfig()</methodname> .
- Básicamente, se crea una configuración compatible con
- <classname>Zend_Config</classname> . Y en su código lo lee y lo
- pasa a RewriteRouter. </para>
- <para> Como ejemplo, considere el siguiente archivo
- <acronym>INI</acronym> : </para>
- <programlisting language="php"><![CDATA[
- [production]
- routes.archive.route = "archive/:year/*"
- routes.archive.defaults.controller = archive
- routes.archive.defaults.action = show
- routes.archive.defaults.year = 2000
- routes.archive.reqs.year = "\d+"
- routes.news.type = "Zend_Controller_Router_Route_Static"
- routes.news.route = "news"
- routes.news.defaults.controller = "news"
- routes.news.defaults.action = "list"
- routes.archive.type = "Zend_Controller_Router_Route_Regex"
- routes.archive.route = "archive/(\d+)"
- routes.archive.defaults.controller = "archive"
- routes.archive.defaults.action = "show"
- routes.archive.map.1 = "year"
- ; O: routes.archive.map.year = 1
- ]]></programlisting>
- <para> Entonces el archivo <acronym>INI</acronym> puede ser leído por un
- objeto <classname>Zend_Config</classname> como sigue: </para>
- <programlisting language="php"><![CDATA[
- $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
- $router = new Zend_Controller_Router_Rewrite();
- $router->addConfig($config, 'routes');
- ]]></programlisting>
- <para> En el ejemplo de arriba, le decimos el router que utilice la
- sección 'routes' del archivo <acronym>INI</acronym> 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
- <classname>Zend_Controller_Router_Route_Interface</classname> .
- Puede utilizarse una clave opcional 'type' para especificar el tipo
- de clase de ruta a utilizar en esa ruta en particular; por defecto,
- usa <classname>Zend_Controller_Router_Route</classname> . En el
- ejemplo de arriba, la ruta 'news' está definida para usar
- <classname>Zend_Controller_Router_Route_Static</classname> .
- </para>
- </sect2>
- <sect2 id="zend.controller.router.subclassing">
- <title>Subclassing del Router</title>
- <para> 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. </para>
- <para> Dicho esto, en algún momento puede encontrarse a si mismo
- deseando usar un paradigma diferente de routing. La intefaz
- <classname>Zend_Controller_Router_Interface</classname>
- proporciona la información mínima necesaria para crear un router, y
- consiste en un único método. </para>
- <programlisting language="php"><![CDATA[
- interface Zend_Controller_Router_Interface
- {
- /**
- * @param Zend_Controller_Request_Abstract $request
- * @throws Zend_Controller_Router_Exception
- * @return Zend_Controller_Request_Abstract
- */
- public function route(Zend_Controller_Request_Abstract $request);
- }
- ]]></programlisting>
- <para> 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. </para>
- </sect2>
- </sect1>
|