Cómo usar el enrutador de Apache

Si bien Symfony2, es muy rápido fuera de la caja, también proporciona varias maneras de aumentar esa velocidad con unos cuantos ajustes. Una de esas maneras es dejando que Apache maneje el enrutado directamente, en lugar de utilizar Symfony2 para esta tarea.

Cambiando los parámetros de configuración del enrutador

Para volcar las rutas de Apache, primero debes modificar algunos parámetros de configuración para decirle a Symfony2 que utilice el ApacheUrlMatcher en lugar de la opción predeterminada.

  • YAML
    # app/config/config_prod.yml
    
  • XML
    <!-- app/config/config_prod.xml -->
    <parameters>
        <parameter key="router.options.matcher.cache_class">null</parameter> <!-- disable router cache -->
        <parameter key="router.options.matcher_class">
            Symfony\Component\Routing\Matcher\ApacheUrlMatcher
        </parameter>
    </parameters>
    
  • PHP
    // app/config/config_prod.php
    $container->setParameter('router.options.matcher.cache_class', null); // desactuva la caché de enrutado
    $container->setParameter(
        'router.options.matcher_class',
        'Symfony\Component\Routing\Matcher\ApacheUrlMatcher'
    );
    

Truco

Ten en cuenta que Symfony\Component\Routing\Matcher\ApacheUrlMatcher extiende a Symfony\Component\Routing\Matcher\UrlMatcher por lo que incluso si no se regeneran las reglas url_rewrite, todo saldrá bien (porque al final ApacheUrlMatcher::match() hace una llamada a parent::match()).

Generando reglas para mod_rewrite

Para comprobar que está funcionando, vamos a crear una ruta muy básica para el paquete de demostración:

  • YAML
    # app/config/routing.yml
    hello:
        path:  /hello/{name}
        defaults: { _controller: AcmeDemoBundle:Demo:hello }
    
  • XML
    <!-- app/config/routing.xml -->
    <route id="hello" path="/hello/{name}">
        <default key="_controller">AcmeDemoBundle:Demo:hello</default>
    </route>
    
  • PHP
    // app/config/routing.php
    $collection->add('hello', new Route('/hello/{name}', array(
        '_controller' => 'AcmeDemoBundle:Demo:hello',
    )));
    

Ahora genera las reglas url_rewrite:

$ php app/console router:dump-apache -e=prod --no-debug

Lo cual debe mostrar —más o menos— lo siguiente:

# salta peticiones «reales»
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [QSA,L]

# hello
RewriteCond %{REQUEST_URI} ^/hello/([^/]+?)$
RewriteRule .* app.php [QSA,L,E=_ROUTING__route:hello,E=_ROUTING_name:%1,E=_ROUTING__controller:AcmeDemoBundle\:Demo\:hello]

Ahora puedes volver a escribir web/.htaccess para utilizar las nuevas reglas, de modo que este ejemplo debería tener el siguiente aspecto:

<IfModule mod_rewrite.c>
    RewriteEngine On

    # salta peticiones "reales"
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule .* - [QSA,L]

    # hello
    RewriteCond %{REQUEST_URI} ^/hello/([^/]+?)$
    RewriteRule .* app.php [QSA,L,E=_ROUTING__route:hello,E=_ROUTING_name:%1,E=_ROUTING__controller:AcmeDemoBundle\:Demo\:hello]
</IfModule>

Nota

El procedimiento anterior se debe realizar cada vez que añadas/cambies la ruta si quieres sacar el máximo provecho de esta configuración.

¡Eso es todo! Ahora estás listo para usar las reglas de enrutado de Apache.

Ajustes adicionales

Para ahorrar un poco de tiempo en el procesamiento, cambia las ocurrencias de Request a ApacheRequest en web/app.php:

// web/app.php

require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
//require_once __DIR__.'/../app/AppCache.php';

use Symfony\Component\HttpFoundation\ApacheRequest;

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
//$kernel = new AppCache($kernel);
$kernel->handle(ApacheRequest::createFromGlobals())->send();
Bifúrcame en GitHub