hace 9 años
El sistema de eventos de Laravel proporciona una implementación sencilla del patrón observador, permitiéndote suscribirte y escuchar varios eventos que ocurren en tu aplicación. Esta funcionalidad resulta particularmente útil para desacoplar diferentes partes de la lógica de tu aplicación y evitar bloquear el flujo principal de las peticiones. Los listeners encolados pueden utilizarse para manejar tareas que consumen mucho tiempo de forma asíncrona, mejorando así el rendimiento de tu aplicación.

¿Cómo funcionan los eventos en Laravel?
Imagina que tienes una aplicación donde, cuando un usuario realiza un pedido, necesitas realizar varias acciones: enviar un correo electrónico de confirmación, actualizar el inventario, notificar al equipo de logística, etc. En un enfoque tradicional, podrías colocar toda esta lógica directamente en el controlador o el modelo encargado de procesar el pedido. Sin embargo, esto puede llevar a un código muy acoplado, difícil de mantener y escalar.

El sistema de eventos de Laravel te permite abordar este problema de una manera más elegante y flexible. En lugar de acoplar todas estas acciones al proceso principal de pedido, puedes disparar un evento (por ejemplo, PedidoRealizado) cuando se complete el pedido. Luego, puedes crear listeners que escuchen este evento y ejecuten las acciones correspondientes (enviar email, actualizar inventario, notificar logística) de forma independiente.
Configurando un proyecto Laravel para eventos
Para empezar a trabajar con eventos en Laravel, primero necesitas tener un proyecto Laravel funcionando. Si ya tienes uno, puedes saltarte este paso. De lo contrario, crea un nuevo proyecto Laravel utilizando Composer:
composer create-project laravel/laravel nombre-de-tu-proyecto cd nombre-de-tu-proyectoAsegúrate de tener PHP 8.1 o superior y Composer instalados en tu sistema.
Creando un Evento
Un evento en Laravel es simplemente una clase PHP que representa algo que ha sucedido en tu aplicación. Para crear un evento, puedes usar el comando Artisan make:event:
php artisan make:event PedidoRealizadoEsto creará un nuevo archivo de evento en app/Events/PedidoRealizado.php. Puedes modificar este archivo para incluir la información que necesitas pasar a los listeners cuando se dispara el evento. Por ejemplo, si necesitas pasar la instancia del modelo Pedido, puedes hacerlo de la siguiente manera:
pedido = $pedido; } } En este ejemplo, el evento PedidoRealizado recibe una instancia de Pedido en su constructor, que luego estará disponible para los listeners.
Creando un Listener
Un listener es una clase que contiene la lógica que se ejecutará cuando se dispara un evento específico. Para crear un listener, utiliza el comando Artisan make:listener:
php artisan make:listener EnviarConfirmacionPedido --event=PedidoRealizadoEsto creará un nuevo archivo listener en app/Listeners/EnviarConfirmacionPedido.php. La opción --event=PedidoRealizado indica que este listener está destinado a escuchar el evento PedidoRealizado. El contenido del listener podría ser algo como esto:
pedido->id); // Otras acciones relacionadas con la confirmación del pedido Log::info('Notificación Slack enviada para el pedido #' . $event->pedido->id); Log::info('Notificación SMS enviada para el pedido #' . $event->pedido->id); Log::info('Actualizar inventario para el pedido #' . $event->pedido->id); } } Observa que este listener implementa la interfaz ShouldQueue. Esto indica a Laravel que este listener debe ser ejecutado en cola, es decir, de forma asíncrona. Esto es crucial para tareas que pueden llevar tiempo, como enviar correos electrónicos, ya que evita bloquear la respuesta de la aplicación al usuario.

Si no implementaras ShouldQueue, el listener se ejecutaría de forma síncrona, lo que podría ralentizar la respuesta de tu aplicación. Sin embargo, en algunos casos, la ejecución síncrona puede ser deseable.
Registrando Eventos y Listeners
En Laravel 11.x y versiones posteriores, los eventos y listeners se descubren automáticamente, por lo que no necesitas registrarlos manualmente. Si estás utilizando una versión anterior de Laravel, puedes registrarlos en el archivo EventServiceProvider (app/Providers/EventServiceProvider.php).
Para versiones anteriores, dentro del método boot del EventServiceProvider, definirías un array $listen donde especificas qué listeners deben escuchar qué eventos:
protected $listen = [ \App\Events\PedidoRealizado::class => [ \App\Listeners\EnviarConfirmacionPedido::class, ], ]; Consulta la documentación de Laravel para obtener más detalles sobre el registro de eventos y listeners en versiones anteriores.
Disparando un Evento
Una vez que has creado el evento y el listener, necesitas disparar el evento en el lugar adecuado de tu aplicación. Por ejemplo, en un controlador después de crear un nuevo pedido:
$request->cliente_nombre, 'total' => $request->total, ]); event(new PedidoRealizado($pedido)); return response()->json(['mensaje' => 'Pedido realizado con éxito', 'pedido' => $pedido]); } } Aquí, la función helper event() se utiliza para disparar el evento PedidoRealizado, pasando la instancia del pedido al constructor del evento. Esto permite que el listener acceda a los detalles del pedido cuando se active el evento.

Probando el Sistema de Eventos
Para probar el sistema de eventos, puedes utilizar herramientas como Postman o curl para enviar una petición POST al endpoint /api/pedidos (asumiendo que has definido una ruta para ello). Por ejemplo, con curl:
curl -X POST http://tu-aplicacion.test/api/pedidos \ -H "Content-Type: application/json" \ -d '{"cliente_nombre":"Juan Perez","total":99.99}' Reemplaza tu-aplicacion.test con la URL de tu aplicación.
Si todo está configurado correctamente, deberías ver un nuevo pedido en tu base de datos. Sin embargo, es posible que no veas los mensajes de log del listener inmediatamente, ya que está en cola. Para procesar los trabajos en cola, necesitas ejecutar el worker de la cola:
php artisan queue:workEste comando inicia el worker de la cola, que procesará cualquier trabajo encolado, incluyendo el listener de confirmación de pedido. Una vez que el worker está funcionando, deberías ver los mensajes de log del listener en el archivo de logs de Laravel.
Transacciones de Base de Datos con Eventos
Cuando trabajas con operaciones de base de datos y eventos, es importante entender cómo Laravel maneja los listeners encolados dentro de las transacciones de base de datos. Para asegurar la consistencia de los datos y que los listeners se disparen en el momento correcto, puedes utilizar transacciones de base de datos.
Puedes modificar el controlador para utilizar una transacción de base de datos:
$request->cliente_nombre, 'total' => $request->total, ]); event(new PedidoRealizado($pedido)); return $pedido; }); return response()->json(['mensaje' => 'Pedido realizado con éxito', 'pedido' => $pedido]); } } Y puedes actualizar el listener para que se ejecute después de que la transacción de la base de datos se haya completado exitosamente, implementando la interfaz ShouldHandleEventsAfterCommit:
pedido->id); } } Al implementar ShouldHandleEventsAfterCommit, le indicas a Laravel que procese este listener solo después de que todas las transacciones de base de datos abiertas se hayan confirmado. Esto es fundamental cuando tu listener depende de cambios en la base de datos realizados dentro de la transacción.

Si la opción de configuración after_commit de tu conexión de cola está establecida en true en config/queue.php, todos tus listeners encolados esperarán automáticamente a que se confirmen las transacciones de base de datos abiertas antes de ser procesados, y no necesitarás usar la interfaz ShouldHandleEventsAfterCommit.
Conclusión
El sistema de eventos y listeners de Laravel es una herramienta poderosa para construir aplicaciones más desacopladas, mantenibles y escalables. Permite separar preocupaciones y manejar tareas asíncronas de manera eficiente, mejorando la experiencia del usuario y la robustez de tu aplicación.
Para profundizar en este tema, considera explorar herramientas como Supervisor para gestionar los workers de la cola en un entorno de producción y Laravel Horizon para monitorizar y gestionar tus colas de forma visual.
Preguntas Frecuentes
¿Cuál es la diferencia entre un evento y un listener en Laravel?
Para simplificar, podemos decir que un evento es una acción que ocurre en la aplicación, y el listener es la operación que responde a ese evento. En el ejemplo anterior, PedidoRealizado es el evento (la acción de realizar un pedido) y EnviarConfirmacionPedido es el listener (la operación de enviar un correo de confirmación en respuesta al pedido realizado).
