How to run Laravel source code?

Eventos y Listeners en Laravel: Desacoplando tu Aplicación

hace 9 años

★★★★★Valoración: 4.18 (7157 votos)

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.

Índice de Contenido

¿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.

What is event sourcing in Laravel?
Event sourcing is to data what Git is to code. Most applications only have their current state stored in a database. A lot of useful information gets lost: you don't know how the application got to this state. Event sourcing tries to solve this problem by storing all events that happen in your app.

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-proyecto

Asegú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 PedidoRealizado

Esto 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=PedidoRealizado

Esto 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.

How to use event in Laravel?
An event in Laravel is a simple class that represents something that has happened in your application. Events can be used to trigger actions or notify other parts of your application that something has occurred. This event will carry the Order model instance, allowing listeners to access the order details.

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.

What is the difference between event and listener in Laravel?
To simplify, we can say an event is an action taken in the application, and the listener is the operation that responds to the event. In this tutorial, we will learn and explore Laravel 8 events and listeners. We will develop a small demo application in which we will send an email whenever a user is created.

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:work

Este 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.

What is event sourcing in Laravel?
Event sourcing is to data what Git is to code. Most applications only have their current state stored in a database. A lot of useful information gets lost: you don't know how the application got to this state. Event sourcing tries to solve this problem by storing all events that happen in your app.

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).

Subir