Prologo
Primi Passi
Architettura
Le Basi
- Routing
- Middleware
- Protezione da CSRF
- Controller
- Richieste
- Risposte
- Views
- Blade
- Vite
- URL
- Sessioni
- Validazione
- Errori
- Logging
Approfondimenti
- Artisan
- Broadcasting
- Cache
- Collezioni
- Concorrenza
- Contesto
- Contratti
- Eventi
- File System
- Helpers
- Client HTTP
- Localizzazione
- Notifiche
- Sviluppo di Package
- Processi
- Code
- Rate-limiting
- Stringhe
- Scheduling di Task
Sicurezza
Database
Eloquent ORM
Testing
Package
Eventi
- Introduzione
- Generare Eventi e Listener
- Registrazione di Eventi e Listener
- Definire gli Eventi
- Definizione dei Listener
- Listener di Eventi in Coda
- Invio degli Eventi
- Sottoscrittori di Eventi
- Testing
Introduzione
Gli eventi di Laravel offrono un’implementazione semplice del pattern observer, permettendoti di iscriverti e ascoltare vari eventi che si verificano all’interno della tua applicazione. Le classi degli eventi sono solitamente memorizzate nella directory app/Events
, mentre i loro listener si trovano in app/Listeners
. Non preoccuparti se non vedi queste directory nella tua applicazione, poiché verranno create automaticamente quando generi eventi e listener usando i comandi della console Artisan.
Gli eventi sono un ottimo modo per disaccoppiare vari aspetti della tua applicazione, poiché un singolo evento può avere più listener che non dipendono l’uno dall’altro. Ad esempio, potresti voler inviare una notifica su Slack al tuo utente ogni volta che un ordine viene spedito. Invece di collegare il codice di elaborazione degli ordini al codice della notifica su Slack, puoi generare un evento App\Events\OrderShipped
che un listener può ricevere e utilizzare per inviare una notifica su Slack.
Generare Eventi e Listener
Per generare rapidamente eventi e listener, puoi usare i comandi Artisan make:event
e make:listener
:
php artisan make:event PodcastProcessed
php artisan make:listener SendPodcastNotification --event=PodcastProcessed
Per comodità, puoi anche eseguire i comandi Artisan make:event
e make:listener
senza argomenti aggiuntivi. In questo modo, Laravel ti chiederà automaticamente il nome della classe e, quando crei un listener, l’evento a cui deve ascoltare:
php artisan make:event
php artisan make:listener
Registrazione di Eventi e Listener
Scoperta degli Eventi
Per impostazione predefinita, Laravel trova e registra automaticamente i tuoi event listener scansionando la directory Listeners
della tua applicazione. Quando Laravel trova un metodo di una classe listener che inizia con handle
o __invoke
, registrerà quei metodi come listener per l’evento indicato nel tipo di parametro nella firma del metodo:
use App\Events\PodcastProcessed;
class SendPodcastNotification
{
/**
* Gestisce l'evento specificato.
*/
public function handle(PodcastProcessed $event): void
{
// ...
}
}
Puoi ascoltare più eventi usando i tipi unione di PHP:
/**
* Gestisce l'evento specificato.
*/
public function handle(PodcastProcessed|PodcastPublished $event): void
{
// ...
}
Se prevedi di memorizzare i tuoi listener in una directory diversa o in più directory, puoi dire a Laravel di scansionare quelle directory usando il metodo withEvents
nel file bootstrap/app.php
della tua applicazione:
->withEvents(discover: [
__DIR__.'/../app/Domain/Orders/Listeners',
])
Il comando event:list
può essere usato per elencare tutti i listener registrati nella tua applicazione:
php artisan event:list
Scoperta degli Eventi in Produzione
Per aumentare la velocità della tua applicazione, dovresti memorizzare nella cache un manifesto di tutti i listener della tua applicazione usando i comandi Artisan optimize
o event:cache
. Di solito, questo comando dovrebbe essere eseguito come parte del processo di distribuzione della tua applicazione. Questo manifesto verrà utilizzato dal framework per velocizzare il processo di registrazione degli eventi. Il comando event:clear
può essere usato per eliminare la cache degli eventi.
Registrazione Manuale degli Eventi
Utilizzando il facade Event
, puoi registrare manualmente gli eventi e i relativi listener all’interno del metodo boot
del AppServiceProvider
della tua applicazione:
use App\Domain\Orders\Events\PodcastProcessed;
use App\Domain\Orders\Listeners\SendPodcastNotification;
use Illuminate\Support\Facades\Event;
/**
* Inizializza i servizi dell'applicazione.
*/
public function boot(): void
{
Event::listen(
PodcastProcessed::class,
SendPodcastNotification::class,
);
}
Il comando event:list
può essere utilizzato per elencare tutti i listener registrati nella tua applicazione:
php artisan event:list
Listener con Closure
Di solito, i listener sono definiti come classi; tuttavia, puoi anche registrare manualmente listener di eventi basati su closure nel metodo boot
dell’AppServiceProvider
della tua applicazione:
use App\Events\PodcastProcessed;
use Illuminate\Support\Facades\Event;
/**
* Avvia i servizi dell'applicazione.
*/
public function boot(): void
{
Event::listen(function (PodcastProcessed $event) {
// ...
});
}
Listener Anonimi in Coda
Quando registri listener di eventi basati su closure, puoi racchiudere la closure del listener all’interno della funzione Illuminate\Events\queueable
per istruire Laravel ad eseguire il listener utilizzando il sistema delle code:
use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Event::listen(queueable(function (PodcastProcessed $event) {
// ...
}));
}
Come i job in coda, puoi usare i metodi onConnection
, onQueue
e delay
per personalizzare l’esecuzione del listener in coda:
Event::listen(queueable(function (PodcastProcessed $event) {
// ...
})->onConnection('redis')->onQueue('podcasts')->delay(now()->addSeconds(10)));
Se desideri gestire i fallimenti dei listener anonimi in coda, puoi fornire una closure al metodo catch
durante la definizione del listener queueable
. Questa closure riceverà l’istanza dell’evento e l’istanza di Throwable
che ha causato il fallimento 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) {
// Il listener in coda è fallito...
}));
Listener con carattere jolly
Puoi anche registrare listener usando il carattere *
come parametro jolly, permettendoti di catturare più eventi con lo stesso listener. I listener con carattere jolly ricevono il nome dell’evento come primo argomento e l’intero array dei dati dell’evento come secondo argomento:
Event::listen('event.*', function (string $eventName, array $data) {
// ...
});
Definire gli Eventi
Una classe di evento è fondamentalmente un contenitore di dati che tiene le informazioni relative all’evento. Ad esempio, supponiamo che un evento App\Events\OrderShipped
riceva un oggetto 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;
/**
* Crea una nuova istanza dell'evento.
*/
public function __construct(
public Order $order,
) {}
}
Come puoi vedere, questa classe di evento non contiene logica. È un contenitore per l’istanza App\Models\Order
che è stata acquistata. Il trait SerializesModels
utilizzato dall’evento serializzerà correttamente qualsiasi modello Eloquent se l’oggetto evento viene serializzato usando la funzione serialize
di PHP, ad esempio quando si utilizzano listener in coda.
Definizione dei Listener
Successivamente, diamo un’occhiata al listener per il nostro evento di esempio. I listener degli eventi ricevono le istanze degli eventi nel loro metodo handle
. Il comando Artisan make:listener
, quando viene eseguito con l’opzione --event
, importa automaticamente la classe dell’evento corretta e specifica il tipo di evento nel metodo handle
. All’interno del metodo handle
, puoi eseguire tutte le azioni necessarie per rispondere all’evento:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
class SendShipmentNotification
{
/**
* Crea il listener dell'evento.
*/
public function __construct() {}
/**
* Gestisce l'evento.
*/
public function handle(OrderShipped $event): void
{
// Accedi all'ordine usando $event->order...
}
}
I tuoi listener degli eventi possono anche specificare il tipo di eventuali dipendenze di cui hanno bisogno nei loro costruttori. Tutti i listener degli eventi sono risolti tramite il service container di Laravel, quindi le dipendenze verranno iniettate automaticamente.
Fermare la Propagazione di un Evento
A volte, potresti voler fermare la propagazione di un evento ad altri listener. Puoi farlo restituendo false
dal metodo handle
del tuo listener.
Listener di Eventi in Coda
Mettere in coda i listener può essere vantaggioso se il tuo listener deve eseguire un’attività più "lenta" del solito, come inviare un’email o effettuare una richiesta HTTP. Prima di utilizzare listener in coda, assicurati di configurare la tua coda e avviare un worker della coda sul tuo server o nell’ambiente di sviluppo locale.
Per specificare che un listener deve essere messo in coda, aggiungi l’interfaccia ShouldQueue
alla classe del listener. I listener generati dai comandi make:listener
di Artisan hanno già questa interfaccia importata nello spazio dei nomi corrente, quindi puoi usarla subito:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
// ...
}
E tutto qui! Ora, quando un evento gestito da questo listener viene dispatchato, il listener sarà automaticamente messo in coda dall’event dispatcher utilizzando il sistema di coda di Laravel. Se non vengono generate eccezioni quando il listener viene eseguito dalla coda, il job in coda sarà automaticamente eliminato dopo aver finito l’elaborazione.
Personalizzare la Connessione della Queue, il Nome e il Ritardo
Se desideri personalizzare la connessione della queue, il nome della queue o il tempo di ritardo di un event listener, puoi definire le proprietà $connection
, $queue
o $delay
nella tua classe listener:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
/**
* Il nome della connessione a cui il job deve essere inviato.
*
* @var string|null
*/
public $connection = 'sqs';
/**
* Il nome della queue a cui il job deve essere inviato.
*
* @var string|null
*/
public $queue = 'listeners';
/**
* Il tempo (secondi) prima che il job venga elaborato.
*
* @var int
*/
public $delay = 60;
}
Se desideri definire la connessione della queue del listener, il nome della queue o il ritardo a runtime, puoi definire i metodi viaConnection
, viaQueue
o withDelay
nel listener:
/**
* Ottieni il nome della connessione della queue del listener.
*/
public function viaConnection(): string
{
return 'sqs';
}
/**
* Ottieni il nome della queue del listener.
*/
public function viaQueue(): string
{
return 'listeners';
}
/**
* Ottieni il numero di secondi prima che il job venga elaborato.
*/
public function withDelay(OrderShipped $event): int
{
return $event->highPriority ? 0 : 60;
}
Mettere in Coda i Listener a Condizioni Specifiche
A volte, potrebbe essere necessario determinare se un listener debba essere accodato in base ad alcuni dati disponibili solo a runtime. Per fare ciò, è possibile aggiungere un metodo shouldQueue
a un listener per decidere se accodarlo. Se il metodo shouldQueue
restituisce false
, il listener non sarà accodato:
<?php
namespace App\Listeners;
use App\Events\OrderCreated;
use Illuminate\Contracts\Queue\ShouldQueue;
class RewardGiftCard implements ShouldQueue
{
/**
* Reward a gift card to the customer.
*/
public function handle(OrderCreated $event): void
{
// ...
}
/**
* Determine whether the listener should be queued.
*/
public function shouldQueue(OrderCreated $event): bool
{
return $event->order->subtotal >= 5000;
}
}
Interagire Manualmente con la Queue
Se hai bisogno di accedere manualmente ai metodi delete
e release
del job sottostante della coda del listener, puoi farlo utilizzando il trait Illuminate\Queue\InteractsWithQueue
. Questo trait viene importato di default nei listener generati e fornisce accesso a questi metodi:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
/**
* Gestisci l'evento.
*/
public function handle(OrderShipped $event): void
{
if (true) {
$this->release(30);
}
}
}
Listener di Eventi in Coda e Transazioni del Database
Quando i listener in coda vengono eseguiti all’interno di transazioni del database, potrebbero essere gestiti dalla coda prima che la transazione sia confermata. In tal caso, eventuali aggiornamenti apportati ai modelli o ai record del database durante la transazione potrebbero non essere ancora presenti nel database. Inoltre, i modelli o i record creati nella transazione potrebbero non esistere nel database. Se il tuo listener dipende da questi modelli, potrebbero verificarsi errori imprevisti quando il job che dispatcha il listener in coda viene elaborato.
Se l’opzione di configurazione after_commit
della tua connessione di coda è impostata su false
, puoi comunque indicare che un particolare listener in coda debba essere eseguito dopo che tutte le transazioni del database aperte sono state confermate, implementando l’interfaccia ShouldQueueAfterCommit
nella classe del listener:
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
use Illuminate\Queue\InteractsWithQueue;
class SendShipmentNotification implements ShouldQueueAfterCommit
{
use InteractsWithQueue;
}
Per saperne di più su come gestire questi problemi, consulta la documentazione relativa a queued jobs e transazioni del database.
Gestione del Fallimento di Job in Coda
A volte i tuoi listener di eventi in coda possono fallire. Se il listener in coda supera il numero massimo di tentativi come definito dal tuo queue worker, il metodo failed
verrà chiamato sul tuo listener. Il metodo failed
riceve l’istanza dell’evento e il Throwable
che ha causato il fallimento:
<?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;
/**
* Handle the event.
*/
public function handle(OrderShipped $event): void
{
// ...
}
/**
* Handle a job failure.
*/
public function failed(OrderShipped $event, Throwable $exception): void
{
// ...
}
}
Specificare il Numero Massimo di Tentativi per un Listener in Coda
Se uno dei tuoi listener in coda incontra un errore, probabilmente non vuoi che continui a tentare ripetutamente senza fine. Per questo, Laravel offre diverse modalità per specificare quante volte o per quanto tempo un listener può essere tentato.
Puoi definire una proprietà $tries
nella tua classe listener per specificare quante volte il listener può essere provato prima di considerarlo fallito:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
/**
* Il numero di volte che il listener in coda può essere tentato.
*
* @var int
*/
public $tries = 5;
}
In alternativa a definire quante volte un listener può essere tentato prima di fallire, puoi definire un tempo oltre il quale il listener non sarà più tentato. Questo permette di provare un listener un numero qualsiasi di volte entro un determinato lasso di tempo. Per definire il momento in cui un listener non deve più essere tentato, aggiungi un metodo retryUntil
alla tua classe listener. Questo metodo deve restituire un’istanza di DateTime
:
use DateTime;
/**
* Determina il momento in cui il listener deve scadere.
*/
public function retryUntil(): DateTime
{
return now()->addMinutes(5);
}
Specificare il Backoff del Listener in Coda
Se desideri configurare quanti secondi Laravel dovrebbe attendere prima di tentare nuovamente un listener che ha incontrato un’eccezione, puoi farlo definendo una proprietà backoff
nella tua classe listener:
/**
* Il numero di secondi da attendere prima di riprovare il listener in coda.
*
* @var int
*/
public $backoff = 3;
Se hai bisogno di una logica più complessa per determinare il tempo di backoff del listener, puoi definire un metodo backoff
nella tua classe listener:
/**
* Calcola il numero di secondi da attendere prima di riprovare il listener in coda.
*/
public function backoff(): int
{
return 3;
}
Puoi facilmente configurare dei backoff "esponenziali" restituendo un array di valori di backoff dal metodo backoff
. In questo esempio, il ritardo del retry sarà di 1 secondo per il primo tentativo, 5 secondi per il secondo tentativo, 10 secondi per il terzo tentativo, e 10 secondi per ogni retry successivo se ci sono altri tentativi rimanenti:
/**
* Calcola il numero di secondi da attendere prima di riprovare il listener in coda.
*
* @return array<int, int>
*/
public function backoff(): array
{
return [1, 5, 10];
}
Invio degli Eventi
Per inviare un evento, puoi chiamare il metodo statico dispatch
sull’evento. Questo metodo è reso disponibile sull’evento tramite il trait Illuminate\Foundation\Events\Dispatchable
. Qualsiasi argomento passato al metodo dispatch
verrà passato al costruttore dell’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
{
/**
* Spedisci l'ordine dato.
*/
public function store(Request $request): RedirectResponse
{
$order = Order::findOrFail($request->order_id);
// Logica di spedizione dell'ordine...
OrderShipped::dispatch($order);
return redirect('/orders');
}
}
Se desideri inviare un evento condizionatamente, puoi usare i metodi dispatchIf
e dispatchUnless
:
OrderShipped::dispatchIf($condition, $order);
OrderShipped::dispatchUnless($condition, $order);
Durante i test, può essere utile verificare che determinati eventi siano stati inviati senza realmente attivare i loro listener. Gli helper di test integrati di Laravel semplificano questo compito.
Invio di Eventi Dopo le Transazioni di Database
A volte potresti voler istruire Laravel a inviare un evento solo dopo che la transazione di database attiva è stata confermata. Per fare ciò, puoi implementare l’interfaccia ShouldDispatchAfterCommit
nella classe dell’evento.
Questa interfaccia indica a Laravel di non inviare l’evento fino a quando la transazione di database corrente non è stata confermata. Se la transazione fallisce, l’evento verrà scartato. Se non c’è alcuna transazione di database in corso quando l’evento viene inviato, l’evento verrà inviato immediatamente:
<?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;
/**
* Crea una nuova istanza dell'evento.
*/
public function __construct(
public Order $order,
) {}
}
Sottoscrittori di Eventi
Scrivere Subscriber di Eventi
I subscriber di eventi sono classi che possono iscriversi a più eventi direttamente all’interno della classe subscriber, permettendo di definire diversi gestori di eventi in un’unica classe. I subscriber devono definire un metodo subscribe
, al quale verrà passata un’istanza di event dispatcher. Puoi chiamare il metodo listen
sul dispatcher fornito per registrare i listener degli eventi:
<?php
namespace App\Listeners;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;
class UserEventSubscriber
{
/**
* Gestisce gli eventi di login dell'utente.
*/
public function handleUserLogin(Login $event): void {}
/**
* Gestisce gli eventi di logout dell'utente.
*/
public function handleUserLogout(Logout $event): void {}
/**
* Registra i listener per il subscriber.
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
Login::class,
[UserEventSubscriber::class, 'handleUserLogin']
);
$events->listen(
Logout::class,
[UserEventSubscriber::class, 'handleUserLogout']
);
}
}
Se i metodi listener degli eventi sono definiti all’interno del subscriber stesso, potresti trovare più comodo restituire un array di eventi e nomi di metodi dal metodo subscribe
del subscriber. Laravel determinerà automaticamente il nome della classe del subscriber durante la registrazione dei listener degli eventi:
<?php
namespace App\Listeners;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;
class UserEventSubscriber
{
/**
* Gestisce gli eventi di login dell'utente.
*/
public function handleUserLogin(Login $event): void {}
/**
* Gestisce gli eventi di logout dell'utente.
*/
public function handleUserLogout(Logout $event): void {}
/**
* Registra i listener per il subscriber.
*
* @return array<string, string>
*/
public function subscribe(Dispatcher $events): array
{
return [
Login::class => 'handleUserLogin',
Logout::class => 'handleUserLogout',
];
}
}
Registrare gli Event Subscribers
Dopo aver creato lo subscriber, Laravel registrerà automaticamente i metodi gestori all’interno dello subscriber se seguono le convenzioni di scoperta eventi di Laravel. Altrimenti, puoi registrare manualmente il tuo subscriber utilizzando il metodo subscribe
della facade Event
. Di solito, questo va fatto nel metodo boot
dell’AppServiceProvider
della tua applicazione:
<?php
namespace App\Providers;
use App\Listeners\UserEventSubscriber;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Event::subscribe(UserEventSubscriber::class);
}
}
Testing
Quando testi del codice che invia eventi, potresti voler istruire Laravel a non eseguire effettivamente i listener dell’evento, poiché il codice del listener può essere testato direttamente e separatamente dal codice che invia l’evento corrispondente. Naturalmente, per testare il listener stesso, puoi istanziare un’istanza del listener e invocare direttamente il metodo handle
nel tuo test.
Utilizzando il metodo fake
della facade Event
, puoi impedire l’esecuzione dei listener, eseguire il codice in prova e poi verificare quali eventi sono stati inviati dalla tua applicazione usando i metodi assertDispatched
, assertNotDispatched
e assertNothingDispatched
:
<?php
use App\Events\OrderFailedToShip;
use App\Events\OrderShipped;
use Illuminate\Support\Facades\Event;
test('orders can be shipped', function () {
Event::fake();
// Esegui la spedizione dell'ordine...
// Verifica che un evento sia stato inviato...
Event::assertDispatched(OrderShipped::class);
// Verifica che un evento sia stato inviato due volte...
Event::assertDispatched(OrderShipped::class, 2);
// Verifica che un evento non sia stato inviato...
Event::assertNotDispatched(OrderFailedToShip::class);
// Verifica che nessun evento sia stato inviato...
Event::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
{
/**
* Testa la spedizione dell'ordine.
*/
public function test_orders_can_be_shipped(): void
{
Event::fake();
// Esegui la spedizione dell'ordine...
// Verifica che un evento sia stato inviato...
Event::assertDispatched(OrderShipped::class);
// Verifica che un evento sia stato inviato due volte...
Event::assertDispatched(OrderShipped::class, 2);
// Verifica che un evento non sia stato inviato...
Event::assertNotDispatched(OrderFailedToShip::class);
// Verifica che nessun evento sia stato inviato...
Event::assertNothingDispatched();
}
}
Puoi passare una closure ai metodi assertDispatched
o assertNotDispatched
per verificare che un evento sia stato inviato e che superi un determinato "test di verità". Se almeno un evento viene inviato e supera il test di verità dato, l’asserzione avrà successo:
Event::assertDispatched(function (OrderShipped $event) use ($order) {
return $event->order->id === $order->id;
});
Se desideri semplicemente verificare che un listener di eventi stia ascoltando un determinato evento, puoi usare il metodo assertListening
:
Event::assertListening(
OrderShipped::class,
SendShipmentNotification::class
);
Dopo aver chiamato
Event::fake()
, nessun listener di eventi verrà eseguito. Quindi, se i tuoi test utilizzano factory di modelli che si basano sugli eventi, come la creazione di un UUID durante l’eventocreating
di un modello, dovresti chiamareEvent::fake()
dopo aver utilizzato le tue factory.
Simulare un Sottoinsieme di Eventi
Se desideri simulare i listener degli eventi solo per un insieme specifico di eventi, puoi passarli al metodo fake
o fakeFor
:
test('orders can be processed', function () {
Event::fake([
OrderCreated::class,
]);
$order = Order::factory()->create();
Event::assertDispatched(OrderCreated::class);
// Altri eventi vengono dispatchati normalmente...
$order->update([...]);
});
/**
* Test del processo d'ordine.
*/
public function test_orders_can_be_processed(): void
{
Event::fake([
OrderCreated::class,
]);
$order = Order::factory()->create();
Event::assertDispatched(OrderCreated::class);
// Altri eventi vengono dispatchati normalmente...
$order->update([...]);
}
Puoi simulare tutti gli eventi tranne un insieme di eventi specificati usando il metodo except
:
Event::fake()->except([
OrderCreated::class,
]);
Falsi Eventi con Ambito
Se desideri falsificare solo i listener degli eventi per una parte del tuo test, puoi usare il metodo fakeFor
:
<?php
use App\Events\OrderCreated;
use App\Models\Order;
use Illuminate\Support\Facades\Event;
test('orders can be processed', function () {
$order = Event::fakeFor(function () {
$order = Order::factory()->create();
Event::assertDispatched(OrderCreated::class);
return $order;
});
// Gli eventi vengono dispatchati normalmente e gli osservatori verranno eseguiti...
$order->update([...]);
});
<?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 del processo d'ordine.
*/
public function test_orders_can_be_processed(): void
{
$order = Event::fakeFor(function () {
$order = Order::factory()->create();
Event::assertDispatched(OrderCreated::class);
return $order;
});
// Gli eventi vengono dispatchati normalmente e gli osservatori verranno eseguiti...
$order->update([...]);
}
}