Estamos actualizando el sitio. Durante unos días es posible que veas fallos de diseño o de traducción. La documentación sigue disponible: si una página se ve mal, recárgala más tarde.

Eventos

10.x 7 de mar. de 2026

#Introducción

Los eventos de Laravel proporcionan una implementación sencilla del patrón observer, permitiéndole suscribirse y escuchar diversos eventos que ocurren dentro de su aplicación. Las clases de eventos normalmente se almacenan en el directorio app/Events, mientras que sus listeners se almacenan en app/Listeners. No se preocupe si no ve estos directorios en su aplicación, ya que se crearán automáticamente cuando genere eventos y listeners usando comandos de consola Artisan.

Los eventos son una excelente forma de desacoplar diferentes aspectos de su aplicación, ya que un solo evento puede tener múltiples listeners que no dependen entre sí. Por ejemplo, puede que desee enviar una notificación por Slack a su usuario cada vez que un pedido haya sido enviado. En lugar de acoplar su código de procesamiento de pedidos con el código de notificación de Slack, puede lanzar un evento App\Events\OrderShipped que un listener recibirá y usará para despachar la notificación por Slack.

#Registro de Eventos y Listeners

El App\Providers\EventServiceProvider incluido en su aplicación Laravel proporciona un lugar conveniente para registrar todos los listeners de eventos de su aplicación. La propiedad listen contiene un arreglo con todos los eventos (claves) y sus listeners (valores). Puede agregar tantos eventos a este arreglo como su aplicación requiera. Por ejemplo, agreguemos un evento OrderShipped:

use App\Events\OrderShipped;
use App\Listeners\SendShipmentNotification;

/**
 * Mapeo de listeners de eventos para la aplicación.
 *
 * @var array<class-string, array<int, class-string>>
 */
protected $listen = [
    OrderShipped::class => [
        SendShipmentNotification::class,
    ],
];
Примечание

El comando event:list puede usarse para mostrar una lista de todos los eventos y listeners registrados por su aplicación.

#Generación de Eventos y Listeners

Por supuesto, crear manualmente los archivos para cada evento y listener es tedioso. En su lugar, agregue listeners y eventos a su EventServiceProvider y use el comando Artisan event:generate. Este comando generará cualquier evento o listener listado en su EventServiceProvider que aún no exista:

php artisan event:generate

Alternativamente, puede usar los comandos Artisan make:event y make:listener para generar eventos y listeners individuales:

php artisan make:event PodcastProcessed

php artisan make:listener SendPodcastNotification --event=PodcastProcessed

#Registro Manual de Eventos

Normalmente, los eventos deben registrarse a través del arreglo $listen del EventServiceProvider; sin embargo, también puede registrar listeners basados en clases o closures manualmente en el método boot de su EventServiceProvider:

use App\Events\PodcastProcessed;
use App\Listeners\SendPodcastNotification;
use Illuminate\Support\Facades\Event;

/**
 * Registrar otros eventos para su aplicación.
 */
public function boot(): void
{
    Event::listen(
        PodcastProcessed::class,
        SendPodcastNotification::class,
    );

    Event::listen(function (PodcastProcessed $event) {
        // ...
    });
}

#Listeners Anónimos en Cola

Al registrar listeners basados en closures manualmente, puede envolver el closure del listener dentro de la función Illuminate\Events\queueable para indicar a Laravel que ejecute el listener usando la cola:

use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;

/**
 * Registrar otros eventos para su aplicación.
 */
public function boot(): void
{
    Event::listen(queueable(function (PodcastProcessed $event) {
        // ...
    }));
}

Al igual que con los trabajos en cola, puede usar los métodos onConnection, onQueue y delay para personalizar la ejecución del listener en cola:

Event::listen(queueable(function (PodcastProcessed $event) {
    // ...
})->onConnection('redis')->onQueue('podcasts')->delay(now()->addSeconds(10)));

Si desea manejar fallos en listeners anónimos en cola, puede proporcionar un closure al método catch al definir el listener queueable. Este closure recibirá la instancia del evento y la instancia Throwable que causó el fallo del listener:

use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;
use Throwable;

Event::listen(queueable(function (PodcastProcessed $event) {
    // ...
})->catch(function (PodcastProcessed $event, Throwable $e) {
    // El listener en cola falló...
}));

#Listeners de Eventos con Wildcard

Incluso puede registrar listeners usando * como parámetro wildcard, lo que le permite capturar múltiples eventos con el mismo listener. Los listeners wildcard reciben el nombre del evento como primer argumento y el arreglo completo de datos del evento como segundo argumento:

Event::listen('event.*', function (string $eventName, array $data) {
    // ...
});

#Descubrimiento de Eventos

En lugar de registrar eventos y listeners manualmente en el arreglo $listen del EventServiceProvider, puede habilitar el descubrimiento automático de eventos. Cuando el descubrimiento está habilitado, Laravel encontrará y registrará automáticamente sus eventos y listeners escaneando el directorio Listeners de su aplicación. Además, cualquier evento explícitamente definido en el EventServiceProvider seguirá siendo registrado.

Laravel encuentra listeners escaneando las clases listener usando los servicios de reflexión de PHP. Cuando Laravel encuentra algún método en una clase listener que comienza con handle o __invoke, registra esos métodos como listeners para el evento que está tipeado en la firma del método:

use App\Events\PodcastProcessed;

class SendPodcastNotification
{
    /**
     * Manejar el evento dado.
     */
    public function handle(PodcastProcessed $event): void
    {
        // ...
    }
}

El descubrimiento de eventos está deshabilitado por defecto, pero puede habilitarlo sobrescribiendo el método shouldDiscoverEvents en el EventServiceProvider de su aplicación:

/**
 * Determinar si los eventos y listeners deben descubrirse automáticamente.
 */
public function shouldDiscoverEvents(): bool
{
    return true;
}

Por defecto, todos los listeners dentro del directorio app/Listeners de su aplicación serán escaneados. Si desea definir directorios adicionales para escanear, puede sobrescribir el método discoverEventsWithin en su EventServiceProvider:

/**
 * Obtener los directorios de listeners que deben usarse para descubrir eventos.
 *
 * @return array<int, string>
 */
protected function discoverEventsWithin(): array
{
    return [
        $this->app->path('Listeners'),
    ];
}

#Descubrimiento de Eventos en Producción

En producción, no es eficiente que el framework escanee todos sus listeners en cada solicitud. Por lo tanto, durante su proceso de despliegue, debe ejecutar el comando Artisan event:cache para almacenar en caché un manifiesto de todos los eventos y listeners de su aplicación. Este manifiesto será usado por el framework para acelerar el proceso de registro de eventos. El comando event:clear puede usarse para eliminar esta caché.

#Definición de Eventos

Una clase de evento es esencialmente un contenedor de datos que guarda la información relacionada con el evento. Por ejemplo, supongamos que un evento App\Events\OrderShipped recibe un objeto de Eloquent ORM:

<?php

namespace App\Events;

use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class OrderShipped
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Crear una nueva instancia del evento.
     */
    public function __construct(
        public Order $order,
    ) {}
}

Como puede ver, esta clase de evento no contiene lógica. Es un contenedor para la instancia App\Models\Order que fue comprada. El trait SerializesModels usado por el evento serializará de forma elegante cualquier modelo Eloquent si el objeto del evento es serializado usando la función serialize de PHP, como cuando se utilizan listeners en cola.

#Definición de Listeners

A continuación, veamos el listener para nuestro evento de ejemplo. Los listeners de eventos reciben instancias de eventos en su método handle. Los comandos Artisan event:generate y make:listener importarán automáticamente la clase de evento correcta y tipearán el evento en el método handle. Dentro del método handle, puede realizar cualquier acción necesaria para responder al evento:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;

class SendShipmentNotification
{
    /**
     * Crear el listener del evento.
     */
    public function __construct()
    {
        // ...
    }

    /**
     * Manejar el evento.
     */
    public function handle(OrderShipped $event): void
    {
        // Acceder al pedido usando $event->order...
    }
}
Примечание

Sus listeners de eventos también pueden tipear cualquier dependencia que necesiten en sus constructores. Todos los listeners de eventos se resuelven a través del service container de Laravel, por lo que las dependencias serán inyectadas automáticamente.

#Detener la Propagación de un Evento

A veces, puede que desee detener la propagación de un evento a otros listeners. Puede hacerlo retornando false desde el método handle de su listener.

#Listeners de Eventos en Cola

Poner listeners en cola puede ser beneficioso si su listener va a realizar una tarea lenta, como enviar un correo electrónico o hacer una solicitud HTTP. Antes de usar listeners en cola, asegúrese de configurar su cola y de iniciar un worker de cola en su servidor o entorno local de desarrollo.

Para especificar que un listener debe ser puesto en cola, agregue la interfaz ShouldQueue a la clase listener. Los listeners generados por los comandos Artisan event:generate y make:listener ya tienen esta interfaz importada en el namespace actual, por lo que puede usarla inmediatamente:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    // ...
}

¡Eso es todo! Ahora, cuando un evento manejado por este listener sea despachado, el listener será automáticamente puesto en cola por el despachador de eventos usando el sistema de colas de Laravel. Si no se lanzan excepciones cuando el listener es ejecutado por la cola, el trabajo en cola será eliminado automáticamente después de finalizar su procesamiento.

#Personalización de la Conexión, Nombre y Retraso de la Cola

Si desea personalizar la conexión de la cola, el nombre de la cola o el tiempo de retraso de un listener de eventos, puede definir las propiedades $connection, $queue o $delay en su clase listener:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    /**
     * El nombre de la conexión a la que debe enviarse el trabajo.
     *
     * @var string|null
     */
    public $connection = 'sqs';

    /**
     * El nombre de la cola a la que debe enviarse el trabajo.
     *
     * @var string|null
     */
    public $queue = 'listeners';

    /**
     * El tiempo (en segundos) antes de que el trabajo sea procesado.
     *
     * @var int
     */
    public $delay = 60;
}

Si desea definir la conexión de la cola, el nombre de la cola o el retraso del listener en tiempo de ejecución, puede definir los métodos viaConnection, viaQueue o withDelay en el listener:

/**
 * Obtener el nombre de la conexión de la cola del listener.
 */
public function viaConnection(): string
{
    return 'sqs';
}

/**
 * Obtener el nombre de la cola del listener.
 */
public function viaQueue(): string
{
    return 'listeners';
}

/**
 * Obtener el número de segundos antes de que el trabajo sea procesado.
 */
public function withDelay(OrderShipped $event): int
{
    return $event->highPriority ? 0 : 60;
}

#Poner Listeners en Cola Condicionalmente

A veces, puede necesitar determinar si un listener debe ser puesto en cola basándose en datos que solo están disponibles en tiempo de ejecución. Para lograr esto, puede agregar un método shouldQueue a un listener para determinar si debe ser puesto en cola. Si el método shouldQueue retorna false, el listener no será ejecutado:

<?php

namespace App\Listeners;

use App\Events\OrderCreated;
use Illuminate\Contracts\Queue\ShouldQueue;

class RewardGiftCard implements ShouldQueue
{
    /**
     * Recompensar con una tarjeta de regalo al cliente.
     */
    public function handle(OrderCreated $event): void
    {
        // ...
    }

    /**
     * Determinar si el listener debe ser puesto en cola.
     */
    public function shouldQueue(OrderCreated $event): bool
    {
        return $event->order->subtotal >= 5000;
    }
}

#Interacción Manual con la Cola

Si necesita acceder manualmente a los métodos delete y release del trabajo subyacente en la cola del listener, puede hacerlo usando el trait Illuminate\Queue\InteractsWithQueue. Este trait se importa por defecto en los listeners generados y proporciona acceso a estos métodos:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class SendShipmentNotification implements ShouldQueue
{
    use InteractsWithQueue;

    /**
     * Manejar el evento.
     */
    public function handle(OrderShipped $event): void
    {
        if (true) {
            $this->release(30);
        }
    }
}

#Listeners en Cola y Transacciones de Base de Datos

Cuando los listeners en cola se despachan dentro de transacciones de base de datos, pueden ser procesados por la cola antes de que la transacción haya sido confirmada. Cuando esto sucede, cualquier actualización que haya hecho a modelos o registros de base de datos durante la transacción puede que aún no se refleje en la base de datos. Además, cualquier modelo o registro creado dentro de la transacción puede que no exista aún en la base de datos. Si su listener depende de estos modelos, pueden ocurrir errores inesperados cuando el trabajo que despacha el listener en cola es procesado.

Si la opción de configuración after_commit de su conexión de cola está establecida en false, aún puede indicar que un listener en cola particular debe ser despachado después de que todas las transacciones abiertas de base de datos hayan sido confirmadas implementando la interfaz ShouldHandleEventsAfterCommit en la clase listener:

<?php

namespace App\Listeners;

use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class SendShipmentNotification implements ShouldQueue, ShouldHandleEventsAfterCommit
{
    use InteractsWithQueue;
}
Примечание

Para aprender más sobre cómo manejar estos problemas, por favor revise la documentación sobre trabajos en cola y transacciones de base de datos.

#Manejo de Trabajos Fallidos

A veces sus listeners en cola pueden fallar. Si el listener en cola excede el número máximo de intentos definido por su worker de cola, se llamará al método failed en su listener. El método failed recibe la instancia del evento y el Throwable que causó el fallo:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Throwable;

class SendShipmentNotification implements ShouldQueue
{
    use InteractsWithQueue;

    /**
     * Manejar el evento.
     */
    public function handle(OrderShipped $event): void
    {
        // ...
    }

    /**
     * Manejar un fallo en el trabajo.
     */
    public function failed(OrderShipped $event, Throwable $exception): void
    {
        // ...
    }
}

#Especificar el Número Máximo de Intentos para Listeners en Cola

Si uno de sus listeners en cola está encontrando un error, probablemente no quiera que siga intentando indefinidamente. Por lo tanto, Laravel proporciona varias formas para especificar cuántas veces o por cuánto tiempo un listener puede ser intentado.

Puede definir una propiedad $tries en su clase listener para especificar cuántas veces puede intentarse el listener antes de considerarse fallido:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class SendShipmentNotification implements ShouldQueue
{
    use InteractsWithQueue;

    /**
     * El número de veces que puede intentarse el listener en cola.
     *
     * @var int
     */
    public $tries = 5;
}

Como alternativa a definir cuántas veces puede intentarse un listener antes de fallar, puede definir un tiempo límite tras el cual el listener ya no debe ser intentado. Esto permite que un listener sea intentado cualquier número de veces dentro de un marco temporal dado. Para definir el tiempo límite, agregue un método retryUntil a su clase listener. Este método debe retornar una instancia de DateTime:

use DateTime;

/**
 * Determinar el tiempo en que el listener debe expirar.
 */
public function retryUntil(): DateTime
{
    return now()->addMinutes(5);
}

#Despacho de Eventos

Para despachar un evento, puede llamar al método estático dispatch en el evento. Este método está disponible en el evento gracias al trait Illuminate\Foundation\Events\Dispatchable. Cualquier argumento pasado al método dispatch será pasado al constructor del evento:

<?php

namespace App\Http\Controllers;

use App\Events\OrderShipped;
use App\Http\Controllers\Controller;
use App\Models\Order;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class OrderShipmentController extends Controller
{
    /**
     * Enviar el pedido dado.
     */
    public function store(Request $request): RedirectResponse
    {
        $order = Order::findOrFail($request->order_id);

        // Lógica de envío del pedido...

        OrderShipped::dispatch($order);

        return redirect('/orders');
    }
}

Si desea despachar un evento condicionalmente, puede usar los métodos dispatchIf y dispatchUnless:

OrderShipped::dispatchIf($condition, $order);

OrderShipped::dispatchUnless($condition, $order);
Примечание

Al hacer pruebas, puede ser útil afirmar que ciertos eventos fueron despachados sin ejecutar realmente sus listeners. Los helpers de pruebas integrados de Laravel facilitan esto.

#Despacho de Eventos Después de Transacciones de Base de Datos

A veces, puede querer indicar a Laravel que solo despache un evento después de que la transacción activa de base de datos haya sido confirmada. Para ello, puede implementar la interfaz ShouldDispatchAfterCommit en la clase del evento.

Esta interfaz indica a Laravel que no despache el evento hasta que la transacción actual de base de datos sea confirmada. Si la transacción falla, el evento será descartado. Si no hay ninguna transacción de base de datos en curso cuando se despacha el evento, este será despachado inmediatamente:

<?php

namespace App\Events;

use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class OrderShipped implements ShouldDispatchAfterCommit
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Crear una nueva instancia del evento.
     */
    public function __construct(
        public Order $order,
    ) {}
}

#Suscriptores de Eventos

#Escritura de Suscriptores de Eventos

Los suscriptores de eventos son clases que pueden suscribirse a múltiples eventos desde dentro de la propia clase suscriptora, permitiéndole definir varios manejadores de eventos en una sola clase. Los suscriptores deben definir un método subscribe, que recibirá una instancia del despachador de eventos. Puede llamar al método listen en el despachador dado para registrar listeners de eventos:

<?php

namespace App\Listeners;

use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;

class UserEventSubscriber
{
    /**
     * Manejar eventos de inicio de sesión de usuario.
     */
    public function handleUserLogin(Login $event): void {}

    /**
     * Manejar eventos de cierre de sesión de usuario.
     */
    public function handleUserLogout(Logout $event): void {}

    /**
     * Registrar los listeners para el suscriptor.
     */
    public function subscribe(Dispatcher $events): void
    {
        $events->listen(
            Login::class,
            [UserEventSubscriber::class, 'handleUserLogin']
        );

        $events->listen(
            Logout::class,
            [UserEventSubscriber::class, 'handleUserLogout']
        );
    }
}

Si los métodos de sus listeners están definidos dentro del propio suscriptor, puede ser más conveniente retornar un arreglo de eventos y nombres de métodos desde el método subscribe del suscriptor. Laravel determinará automáticamente el nombre de la clase del suscriptor al registrar los listeners:

<?php

namespace App\Listeners;

use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;

class UserEventSubscriber
{
    /**
     * Manejar eventos de inicio de sesión de usuario.
     */
    public function handleUserLogin(Login $event): void {}

    /**
     * Manejar eventos de cierre de sesión de usuario.
     */
    public function handleUserLogout(Logout $event): void {}

    /**
     * Registrar los listeners para el suscriptor.
     *
     * @return array<string, string>
     */
    public function subscribe(Dispatcher $events): array
    {
        return [
            Login::class => 'handleUserLogin',
            Logout::class => 'handleUserLogout',
        ];
    }
}

#Registro de Suscriptores de Eventos

Después de escribir el suscriptor, está listo para registrarlo con el despachador de eventos. Puede registrar suscriptores usando la propiedad $subscribe en el EventServiceProvider. Por ejemplo, agreguemos el UserEventSubscriber a la lista:

<?php

namespace App\Providers;

use App\Listeners\UserEventSubscriber;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * Mapeo de listeners de eventos para la aplicación.
     *
     * @var array
     */
    protected $listen = [
        // ...
    ];

    /**
     * Las clases suscriptoras a registrar.
     *
     * @var array
     */
    protected $subscribe = [
        UserEventSubscriber::class,
    ];
}

#Pruebas

Al probar código que despacha eventos, puede que desee indicar a Laravel que no ejecute realmente los listeners del evento, ya que el código del listener puede probarse directamente y por separado del código que despacha el evento correspondiente. Por supuesto, para probar el listener en sí, puede instanciar un listener y llamar al método handle directamente en su prueba.

Usando el método fake del facade Event, puede evitar que los listeners se ejecuten, ejecutar el código bajo prueba y luego afirmar qué eventos fueron despachados por su aplicación usando los métodos assertDispatched, assertNotDispatched y assertNothingDispatched:

<?php

namespace Tests\Feature;

use App\Events\OrderFailedToShip;
use App\Events\OrderShipped;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * Probar el envío de pedidos.
     */
    public function test_orders_can_be_shipped(): void
    {
        Event::fake();

        // Realizar envío de pedido...

        // Afirmar que un evento fue despachado...
        Event::assertDispatched(OrderShipped::class);

        // Afirmar que un evento fue despachado dos veces...
        Event::assertDispatched(OrderShipped::class, 2);

        // Afirmar que un evento no fue despachado...
        Event::assertNotDispatched(OrderFailedToShip::class);

        // Afirmar que no se despacharon eventos...
        Event::assertNothingDispatched();
    }
}

Puede pasar un closure a los métodos assertDispatched o assertNotDispatched para afirmar que un evento fue despachado que pase una determinada "prueba de verdad". Si al menos un evento fue despachado que pasa la prueba dada, la afirmación será exitosa:

Event::assertDispatched(function (OrderShipped $event) use ($order) {
    return $event->order->id === $order->id;
});

Si simplemente desea afirmar que un listener está escuchando un evento dado, puede usar el método assertListening:

Event::assertListening(
    OrderShipped::class,
    SendShipmentNotification::class
);
Внимание

Después de llamar a Event::fake(), ningún listener de eventos será ejecutado. Por lo tanto, si sus pruebas usan factories de modelos que dependen de eventos, como crear un UUID durante el evento creating de un modelo, debe llamar a Event::fake() después de usar sus factories.

#Falsificación de un Subconjunto de Eventos

Si solo desea falsificar listeners de eventos para un conjunto específico de eventos, puede pasarlos al método fake o fakeFor:

/**
 * Probar el proceso de pedidos.
 */
public function test_orders_can_be_processed(): void
{
    Event::fake([
        OrderCreated::class,
    ]);

    $order = Order::factory()->create();

    Event::assertDispatched(OrderCreated::class);

    // Otros eventos se despachan normalmente...
    $order->update([...]);
}

Puede falsificar todos los eventos excepto un conjunto especificado usando el método except:

Event::fake()->except([
    OrderCreated::class,
]);

#Falsificaciones de Eventos con Ámbito

Si solo desea falsificar listeners de eventos para una parte de su prueba, puede usar el método fakeFor:

<?php

namespace Tests\Feature;

use App\Events\OrderCreated;
use App\Models\Order;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * Test order process.
     */
    public function test_orders_can_be_processed(): void
    {
        $order = Event::fakeFor(function () {
            $order = Order::factory()->create();

            Event::assertDispatched(OrderCreated::class);

            return $order;
        });

        // Los eventos se despachan normalmente y los observers se ejecutan...
        $order->update([...]);
    }
}