# Zend_Controller_Router_Route_Regex

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.

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:

    $route = new Zend_Controller_Router_Route_Regex(
        'archive/(\d+)',
        array(
            'controller' => 'archive',
            'action'     => 'show'
        )
    );
    $router->addRoute('archive', $route);

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

    $values = array(
        1            => '2006',
        'controller' => 'archive',
        'action'     => 'show'
    );

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

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.

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

Puede obtener el contenido de los sub-patrones definidos por la forma habitual:

    public function showAction()
    {
        $request = $this->getRequest();
        $year    = $request->getParam(1); // $year = '2006';
    }

Tenga en cuenta que la clave es un entero (1) en lugar de un string ('1').

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:

    $route = new Zend_Controller_Router_Route_Regex(
        'archive(?:/(\d+))?',
        array(
            1            => '2006',
            'controller' => 'archive',
            'action'     => 'show'
        )
    );
    $router->addRoute('archive', $route);

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:

    $route = new Zend_Controller_Router_Route_Regex(
        'archive/(\d+)',
        array(
            'controller' => 'archive',
            'action' => 'show'
        ),
        array(
            1 => 'year'
        )
    );
    $router->addRoute('archive', $route);

Esto resultaraá en los siguientes valores inyectados a la solicitud:

    $values = array(
        'year'       => '2006',
        'controller' => 'archive',
        'action'     => 'show'
    );

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:

    $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)
    );

Las claves de los sub-patrones deben respresentarse por enteros.

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:

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

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

    $values = array(
        'year'       => '2006',
        2            => 10,
        'controller' => 'archive',
        'action'     => 'show'
    );

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

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

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 URL sin restricción alguna. Imagínese que tiene un blog y desea crear URLs como: `http://domain.com/blog/archive/01-Using_the_Regex_Router.html` , y que tiene que descomponer el último elemento del path `01-Using_the_Regex_Router.html` , 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:

    $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);

Como puede ver, esto añade una enorme cantidad de flexibilidad por encima del standard route.