Symfony2: Compiler pass

Este es un artículo sobre un tema que quería escribir hace tiempo. Esta parte de Symfony2 es una de las que normalmente no se tocan, pero que vale la pena conocer para entender el funcionamiento de Symfony2 y para nuestros bundles.

¿Qué son los compiler passes?

Los compiler passes vienen dados por el componente DependencyInjection y nos permiten manipular la definición de los servicios que se han registrado en el contenedor de servicios. Esto significa que vamos a poder leer las definiciones de los servicios una vez cargadas y modificarlas dinámicamente, cuando veamos ejemplos se entenderá fácilmente. El caso típico de uso de los compiler passes es para los tagged services.

Los compiler passes tienen que implementar la interfaz CompilerPassInterface y normalmente se crean dentro de un directorio llamado Compiler en DependencyInjection del bundle (SMTCBundle\DependencyInjection\Compiler\OurPass.php). Además de esto hay que registrar el compiler pass, esto se hace en el método build del Bundle:

Tagged Services

Cuando se declara un servicio podemos añadirle un tag para poder tratarlo de una forma especial. Por ejemplo cuando queremos añadir una extensión de twig, en el servicio añadimos <tag name="twig.extension" />. Mediante los compiler passes podemos recuperar los servicios que tengan un determinado tag y manipularlos.

Vamos a ver por ejemplo el caso de los listeners. Como ya vimos para añadir listeners tenemos dos tipos de tagskernel.event_listenerkernel.event_subscriber, pero ¿cómo se añaden al dispatcher? Con un compiler pass, más concretamente con RegisterKernelListenersPass:

Esta es la pinta que tiene un compiler pass, como vemos empieza recuperando la definición del servicio event_dispatcher y después recorre todos los servicios que tienen el tag kernel.event_listener (línea 16), se hacen comprobaciones y se añade a la definición de event_dispatcher una llamada a addListenerService con los parámetros del listener (línea 31). A continuación se hace algo similar con los servicios con el tag kernel.event_subscriber.

Además del tag, se pueden añadir otros parámetros adicionales.