vendor riduce i presupposti richiesti durante l’installazione, l’aggiornamento e la creazione della cache.
Questa pagina esamina l’implementazione di Laravel Framework v13.36.0 e applica le operazioni di base sugli eventi alla manutenzione a lungo termine di un pacchetto. Per il caricamento dei provider consulta il package auto-discovery, e per l’ambiente di test consulta Testare pacchetti Laravel.
Registrare esplicitamente i listener del pacchetto
Le operazioni che il pacchetto esegue di default possono essere registrate conEvent::listen() nel metodo boot() di un normale Illuminate\Support\ServiceProvider. La destinazione predefinita del rilevamento automatico dei listener di Laravel è la directory app/Listeners dell’applicazione: la directory src/Listeners all’interno del pacchetto non viene esaminata automaticamente.
Come esempio, creiamo un pacchetto che registra nel log un evento di consegna completata. L’evento è semplicemente una classe che contiene i valori necessari alla notifica.
handle().
extra.laravel.providers di Composer oppure una registrazione esplicita da parte dell’utente. Se l’evento è necessario sia nelle richieste HTTP sia nei queue worker, non limitare la registrazione con runningInConsole().
Registrazione e creazione dell’istanza avvengono in momenti diversi
Dispatcher::listen() aggiunge il listener a un array interno per il nome di evento normale. Quando si passa un nome di classe come sopra, in questo momento l’istanza del listener non viene creata.
Per i listener sincroni, dopo l’emissione dell’evento createClassCallable() risolve la classe tramite make() del container. Per questo motivo è possibile usare la dependency injection nel costruttore.
Questo percorso non esegue call() del container su handle(). Progetta il listener in modo che i servizi necessari vengano iniettati nel costruttore e handle() riceva l’evento. Non considerarlo lo stesso meccanismo della dependency injection in handle() dei comandi Artisan.
Qui si descrivono i listener sincroni. Se implementi ShouldQueue si segue un percorso separato per la coda, quindi consulta anche la gestione in coda degli eventi e le code per transazioni, nuovi tentativi e risoluzione delle dipendenze.
event:cache non blocca la registrazione esplicita
event:cache non è un comando che serializza in blocco tutti i listener registrati nel Dispatcher degli eventi.
EventCacheCommand::getEvents() elenca Illuminate\Foundation\Support\Providers\EventServiceProvider e i provider da esso derivati, e salva i risultati del rilevamento automatico e la mappatura di listens() di ciascun provider. Gli Event::listen() scritti nel ServiceProvider::boot() di un provider normale non rientrano in questa raccolta.
D’altra parte, anche quando la cache esiste, il boot() dei provider normali viene comunque eseguito. Non essere inclusi nella cache e non essere registrati quando la cache esiste sono due cose diverse.
È possibile anche usare
$listen in un pacchetto che estende l’EventServiceProvider di Foundation. Tuttavia, nell’implementazione esaminata, il valore predefinito di shouldDiscoverEvents() è una verifica riferita alla classe base stessa. Estendere la classe non basta perché la directory dei listener del pacchetto venga rilevata automaticamente.
Inoltre, $subscribe e $observers dello stesso provider vengono elaborati separatamente dal ciclo che registra i risultati di getEvents(). Non concludere, guardando solo la cache di $listen, che anche queste registrazioni vengano saltate.
Evitare la doppia registrazione con il rilevamento automatico
Se l’utente aggiunge la directory dei listener del pacchetto conwithEvents(discover: [...]) e anche il provider del pacchetto registra esplicitamente gli stessi listener, l’elaborazione può essere eseguita più volte per un singolo evento.
Per gli eventi normali, Dispatcher::listen() aggiunge elementi a un array e non elimina automaticamente i nomi di classe duplicati a livello dell’intero Dispatcher. Anche array_unique(), eseguito dall’EventServiceProvider di Foundation all’interno della propria mappatura, non è un meccanismo che unifica le registrazioni esplicite effettuate da altri provider.
Assegna la responsabilità della registrazione a una sola parte.
- Se il pacchetto registra i listener predefiniti, non chiedere all’utente di aggiungere quella directory al rilevamento automatico.
- Se l’utente sceglie i listener necessari, il pacchetto fornisce le classi evento e listener e non registra di default gli stessi listener.
- Quando passi dal rilevamento automatico alla registrazione esplicita, indica all’utente di aggiornare anche la configurazione del rilevamento e la vecchia cache degli eventi.
Verificare il comportamento prima e dopo l’aggiornamento
Per controllare lo stato delle registrazioni, eseguievent:list in un’applicazione di verifica in cui è installato il pacchetto. Verifica che il listener interessato sia presente sia senza cache sia con la cache.
event:list non garantisce che il listener completi l’elaborazione né che venga eseguito una sola volta. Aggiungi anche test che emettono realmente l’evento.
Come esempio, dopo aver registrato CourierServiceProvider nel TestCase di base di Testbench, verifichiamo che il logger venga chiamato una sola volta.
Event::fake() è utile per verificare l’emissione degli eventi, ma normalmente impedisce l’esecuzione dei listener reali. In questo test non viene usato perché si verificano registrazione ed elaborazione. Verifica anche la combinazione con il rilevamento automatico e l’avvio con cache in un’app di verifica separata e in una nuova istanza dell’applicazione.
Checklist per la manutenzione a lungo termine
- Documenta i nomi delle classi evento, le proprietà pubbliche e la politica di registrazione dei listener come contratto verso gli utenti.
- Quando modifichi il nome o il payload di eventi a cui gli utenti si iscrivono, comunica le modifiche secondo la gestione della compatibilità tra versioni.
- Negli aggiornamenti che modificano il rilevamento automatico o
$listen, includi la ricreazione dievent:cachenella procedura di deploy. - Distingui i listener predefiniti del pacchetto dai listener personalizzati dell’utente ed evita che lo stesso listener predefinito venga registrato due volte.
- Mantieni, per ogni versione di PHP e Laravel supportata, test che verifichino che il listener venga eseguito una sola volta.