<?xml version="1.0" encoding="UTF-8"?>
    <!-- EN-Revision: 24249 -->
    <!-- Reviewed: no -->
<sect3 id="zend.controller.router.routes.regex">
    <title>Zend_Controller_Router_Route_Regex</title>

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

    <para>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:</para>

    <programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array(
        'controller' => 'archive',
        'action'     => 'show'
    )
);
$router->addRoute('archive', $route);
]]></programlisting>

    <para>
        Cada sub-patrón regex definido será inyectado al objeto solicitud.
        Con nuestro ejemplo
        anterior, después de un matching exitoso
        <filename>http://domain.com/archive/2006</filename>
        , el valor
        resultante del array puede verse como:
    </para>

    <programlisting language="php"><![CDATA[
$values = array(
    1            => '2006',
    'controller' => 'archive',
    'action'     => 'show'
);
]]></programlisting>

    <note>
        <para>
            Las barras de comienzo y final están recortadas de la
            <acronym>URL</acronym>
            en el Router antes de una concordancia.
            Como resultado, coincidendo con la
            <acronym>URL</acronym>
            <filename>http://domain.com/foo/bar/</filename>
            , involucraría al
            regex de
            <filename>foo/bar</filename>
            , y no a
            <filename>/foo/bar</filename>
            .
        </para>
    </note>

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

    <note>
        <para>
            Esta clase de ruta usa el carácter
            <emphasis>#</emphasis>
            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.
        </para>
    </note>

    <para>Puede obtener el contenido de los sub-patrones definidos por la forma
        habitual:</para>

    <programlisting language="php"><![CDATA[
public function showAction()
{
    $request = $this->getRequest();
    $year    = $request->getParam(1); // $year = '2006';
}
]]></programlisting>

    <note>
        <para>Tenga en cuenta que la clave es un entero (1) en lugar de un
            string ('1').</para>
    </note>

    <para>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:</para>

    <programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
    'archive(?:/(\d+))?',
    array(
        1            => '2006',
        'controller' => 'archive',
        'action'     => 'show'
    )
);
$router->addRoute('archive', $route);
]]></programlisting>

    <para>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:</para>

    <programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array(
        'controller' => 'archive',
        'action' => 'show'
    ),
    array(
        1 => 'year'
    )
);
$router->addRoute('archive', $route);
]]></programlisting>

    <para>Esto resultaraá en los siguientes valores inyectados a la solicitud:</para>

    <programlisting language="php"><![CDATA[
$values = array(
    'year'       => '2006',
    'controller' => 'archive',
    'action'     => 'show'
);
]]></programlisting>

    <para>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:</para>

    <programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array( ... ),
    array(1 => 'year')
);

// O

$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array( ... ),
    array('year' => 1)
);
]]></programlisting>

    <note>
        <para>Las claves de los sub-patrones deben respresentarse por enteros.
       </para>
    </note>

    <para>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:</para>

    <programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)/page/(\d+)',
    array( ... ),
    array('year' => 1)
);
]]></programlisting>

    <para>
        Lo que resultará en una mezcla de valores disponibles en la
        solicitud. Como ejemplo, la
        <acronym>URL</acronym>
        <filename>http://domain.com/archive/2006/page/10</filename>
        resultará
        con los siguientes valores:
    </para>

    <programlisting language="php"><![CDATA[
$values = array(
    'year'       => '2006',
    2            => 10,
    'controller' => 'archive',
    'action'     => 'show'
);
]]></programlisting>

    <para>
        Dado que los patrones regex no pueden invertirse fácilmente, tendrá
        que preparar una
        <acronym>URL</acronym>
        inversa si desea usar un
        ayudante de
        <acronym>URL</acronym>
        o incluso un método de ensamble de
        esta clase. Este path inverso está representado por un
        string parseable
        por
        <methodname>sprintf()</methodname>
        y se define como el cuarto parámetro del constructor:
    </para>

    <programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array( ... ),
    array('year' => 1),
    'archive/%s'
);
]]></programlisting>

    <para>
        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
        <acronym>URL</acronym>
        sin restricción alguna.
        Imagínese que tiene un blog y desea crear URLs como:
        <filename>http://domain.com/blog/archive/01-Using_the_Regex_Router.html</filename>
        ,
        y que tiene que descomponer el último elemento del path
        <filename>01-Using_the_Regex_Router.html</filename>
        , en un ID de
        artículo y en el título o 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:
    </para>

    <programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
    'blog/archive/(\d+)-(.+)\.html',
    array(
        'controller' => 'blog',
        'action'     => 'view'
    ),
    array(
        1 => 'id',
        2 => 'description'
    ),
    'blog/archive/%d-%s.html'
);
$router->addRoute('blogArchive', $route);
]]></programlisting>

    <para>Como puede ver, esto añade una enorme cantidad de flexibilidad por
        encima del standard
        route.</para>
</sect3>
