Eventos y Listeners en Laravel
Los Eventos y Listeners en Laravel nos ofrecen una poderosa forma de realizar tareas complejas y desacopladas utilizando el patrón Observer. La idea es más sencilla de lo que parece, pero mejor explicarlo rápidamente con un caso de uso real.
Se realiza un pedido, se envía un correo al cliente con la factura, se envía un correo al comercio informando de la venta, se actualiza el stock.
Los Eventos y Listeners que necesitamos para llevar a cabo esa lógica serían los siguientes.
[Event] NewOrder.
[Listener] SendInvoiceToCustomer.
[Listener] NotifyOrderToAdmin.
[Listener] UpdateStock.
Estoy seguro que ahora todo ha quedado mucho más claro, ¿o no? Seguramente sí, pero ahora es necesario saber cómo implementar esta lógica con código.
Cursos recomendados sobre Eventos y Listeners
Plataforma de cursos con Laravel 7: Vuejs, Roles, Pagos con Stripe SCA, Cupones, Xdebug
Laravel Tenancy V1, Setup completo: DB, Migraciones, Seeds, Rutas y Vistas
Eventos y Listeners en Laravel: ejemplo procesar pedido
Lo primero que debemos hacer para trabajar con Eventos y Listeners en Laravel es crear todos los archivos necesarios, así que vamos a comenzar por la parte más alta de la jerarquía, que en nuestro caso es el Evento.
Los Eventos en Laravel se crean por defecto en el directorio app/Events, así que dirígete a ese directorio y modifica su código por el siguiente.
Fíjate que nuestro Evento no aplica lógica alguna, es muy importante entender esto. El propósito de un evento en Laravel es el de inicializar datos, en nuestro caso el pedido realizado, ¿para qué? Muy sencillo, para que todos los Listeners que estén involucrados con este evento puedan acceder al pedido realizado y así poder realizar las tareas oportunas.
Registrar Eventos en Laravel
Registrar nuestro Evento en Laravel es muy sencillo, aunque es cierto que existen diversas formas, incluso el autoDiscover, lo mejor a nivel de código y rendimiento es hacerlo manualmente en el EventServiceProvider, así que vamos a abrir este archivo para actualizar su código por el siguiente.
Dentro de $listen podemos registrar nuestros Eventos y Listener para que Laravel se encargue del resto. Si te fijas, la clave es nuestro evento y el valor un array, ese array, puede ser un array de clases Listener.
En este punto es súper importante dejar claro que lo que hemos hecho por sí sólo no hace nada, hay que añadir Listeners que estén a la escucha del Evento NewOrder.
Listener para enviar la factura al cliente
Ahora que tenemos el Evento NewOrder, vamos a crear el primer Listener.
Al crear un Listener con el comando make:listener, Artisan nos permite definir el Evento que estará escuchando dicho Listener, lo cuál nos facilita la vida posteriormente a nivel de código. Vamos a abrir el archivo para ver su contenido.
El método handle es la conexión entre nuestro Evento y sus Listeners.
Gracias a haber inicializado el pedido en el Evento NewOrder, en $event->order tenemos toda la información del pedido realizado por nuestro cliente.
Ahora que ya tenemos nuestro Listener listo, vamos a decirle que esté a la escucha del Evento NewOrder, eso lo conseguimos modificando el archivo EventServiceProvider.
El proceso para los Listeners NotifyOrderToAdmin y UpdateStock es exactamente el mismo que el del Listener SendInvoiceToCustomer, así que te lo dejo a ti. Sólo te diré que el EventServiceProvider final debe queda de la siguiente forma.
TIP
Si deseas detener la ejecución de los siguientes Listeners dentro de un Evento simplemente debes retornar false desde el método handle de cualquier Listener, de esta forma, el Evento parará su ejecución.
Disparar Eventos en Laravel
Ahora viene una parte importante de nuestro trabajo, ¿cómo podemos ejecutar un evento desde nuestro código? Muy sencillo, el siguiente ejemplo realiza el trabajo.
El código anterior habrá creado un pedido y ejecutado el Evento NewOrder, el cual están escuchando los Listeners que hemos definido anteriormente. Por lo tanto, todo lo que hemos escrito se estará ejecutando perfectamente.
Jobs y Queues en Eventos y Listeners en Laravel
Un problema en nuestro código es que el proceso es síncrono, es decir, se ejecuta todo de una vez y el usuario deberá esperar a que finalice. ¿Te imaginas tener al usuario viendo una pantalla durante casi un minuto para que se realicen todas las tareas?
Para solucionar este pequeño inconveniente tenemos varias formas, pero en nuestro caso vamos a utilizar los Jobs de Laravel a nivel de base de datos.
Configurar Jobs y Queues en Laravel para base de datos
Para hacer que nuestro Evento NewOrder y sus Listeners se ejecuten en una cola haciendo uso de los Jobs de Laravel, vamos a configurar las colas de Laravel para que trabajen por base de datos.
Los comandos anteriores habrán creado la tabla de jobs en nuestra base de datos, la cuál se encargará de procesar los trabajos que vallamos generando.
Listeners con Queues
Para que nuestros Listeners se ejecuten dentro de las Queues de Laravel necesitamos hacer un ajuste en cada uno de nuestros Listeners, te adjunto un caso y tú actualiza posteriormente cada uno de ellos.
En nuestro caso lo que hacemos es definir el nombre de la conexión que deseamos utilizar, en nuestro caso database, y también el nombre de la cola en la que deseamos añadir estas tareas, en nuestro caso listeners, pero podríamos llamarle de cualquier forma.
Si ahora das de alta un nuevo pedido en tu proyecto verás que lo que sucede no es lo de antes, es decir, ahora no se ejecutaran los listeners, en su lugar, se crearán nuevos registros en la tabla de Jobs de la siguiente forma.
Ejecutar Queues en Laravel
Para finalizar esta entrada, sólo necesitamos saber cómo podemos hacer que los Jobs de nuestra base de datos se ejecuten correctamente, aunque existen varias formas, lo más sencillo es utilizar el siguiente comando.