| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 15103 -->
- <!-- 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 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
- <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 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):
- </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 IIS 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 IIS, <methodname>$_SERVER['REQUEST_URI']</methodname> puede
- no existir, o establecerlo como un string vacío. En este caso,
- <classname>Zend_Controller_Request_Http</classname>
- intentará usar el valor de
- <methodname>$_SERVER['HTTP_X_REWRITE_URL']</methodname>
- 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><xref linkend="zend.controller.router.routes.standard" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.routes.static" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.routes.regex" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.routes.hostname" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.routes.chain" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.default-routes" /> *</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 URL).
- 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 url <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: <methodname>user/martel</methodname>.
- </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 URI. 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 URL
- o de rutas definidas por defecto por el usuario.
- Estas variables son accesibles posteriormente a través de los métodos
- <classname>Zend_Controller_Request::getParam()</classname> o
- <classname>Zend_Controller_Action::_getParam()</classname>.
- </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 URIs
- en la forma de <methodname>controller/action</methodname>.
- Además, se puede especificar un nombre de módulo como primer
- elemento del path, permitiendo URIs de la forma
- <methodname>module/controller/action</methodname>. Por último, también coincidrá
- con cualquier parámetro adicional agregado a la URI por defecto -
- <methodname>controller/action/var1/value1/var2/value2</methodname>.
- </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 <methodname>http://domain.com/~user/application-root/</methodname>)
- en cuyo caso la URL base de la aplicación
- (<methodname>/~user/application-root</methodname>) debe ser detectada
- automáticamente por <classname>Zend_Controller_Request_Http</classname>
- y usada en consecuencia.
- </para>
- <para>
- Si la URL 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 <classname>Zend_Config</classname> 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 INI:
- </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 INI 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 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
- <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>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|