Introducción al sistema de eventos Symfony/EventDispatcher
El sistema de eventos (Event Dispatcher) es uno de los componentes clave del ecosistema Symfony, que implementa los patrones de diseño "Observador" (Observer) y "Mediador" (Mediator). La librería symfony/event-dispatcher proporciona un mecanismo ligero pero potente para crear una arquitectura de aplicación débilmente acoplada. En lugar de vincular rígidamente los componentes con llamadas directas a métodos, puedes "disparar" eventos, y cualquier parte interesada de la aplicación (listeners/suscribers) puede reaccionar a ellos. Esto simplifica drásticamente la ampliación de funcionalidades, las pruebas y el mantenimiento del código.
¿Para qué sirve? Imagina que necesitas registrar cada acción del usuario, enviar una notificación por correo electrónico después del registro y actualizar la caché tras modificar datos. Sin un sistema de eventos, tendrías que insertar llamadas a los servicios correspondientes directamente en los métodos del controlador o del modelo. Esto crea un acoplamiento fuerte y hace que el código sea "frágil". Con EventDispatcher, simplemente disparas el evento UserRegistered, y listeners independientes (logger, mailer, cache) se suscriben a él y realizan su trabajo. Añadir nueva funcionalidad se reduce a escribir un nuevo listener, sin modificar el código existente.
Esta librería no solo se usa en el framework Symfony completo, sino también en microframeworks (Silex, Laravel — tiene su propia implementación, pero el concepto es el mismo), así como en cualquier proyecto PHP que requiera un sistema flexible de hooks y plugins. Es el estándar de facto para la programación orientada a eventos en PHP.
Instalación
La instalación se realiza a través de Composer, el gestor de paquetes estándar para PHP. Abre la terminal en la raíz de tu proyecto y ejecuta el comando:
composer require symfony/event-dispatcher
Si planeas usar un contenedor de inyección de dependencias (Dependency Injection) y el registro automático de listeners, se recomienda instalar también el paquete para trabajar con DependencyInjection (normalmente viene incluido con Symfony Framework). Para uso independiente, solo necesitas symfony/event-dispatcher.
Inicio rápido: ejemplo mínimo funcional
Vamos a crear un sistema simple: dispararemos el evento "order.placed" (pedido realizado) y lo escucharemos.
<?php
// 1. Incluimos el cargador automático de Composer
require_once 'vendor/autoload.php';
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\GenericEvent;
// 2. Creamos el dispatcher
$dispatcher = new EventDispatcher();
// 3. Añadimos un listener (closure) al evento 'order.placed'
$dispatcher->addListener('order.placed', function (GenericEvent $event) {
$orderData = $event->getSubject();
echo "Listener 1: Pedido {$orderData['id']} realizado. Total: {$orderData['total']}\n";
});
// 4. Creamos el evento y le pasamos los datos
$event = new GenericEvent(['id' => 123, 'total' => 2500.00]);
// 5. Despachamos (disparamos) el evento
$dispatcher->dispatch($event, 'order.placed');
// Salida: Listener 1: Pedido 123 realizado. Total: 2500
Este ejemplo muestra la mecánica básica: crear el dispatcher, registrar un listener y enviar un evento. Observa que el listener recibe el objeto del evento, del cual se puede extraer cualquier dato.
Métodos y clases principales
Veamos los 8 elementos clave de la librería que cubren el 90% de los casos de uso.
1. EventDispatcher::addListener()
Firma: addListener(string $eventName, callable $listener, int $priority = 0): void
Qué hace: Registra un listener (callable) para el nombre de evento especificado. Puedes indicar una prioridad: cuanto mayor sea el número, antes se ejecutará el listener.