vendor aan de automatische detectie hoeven toe te voegen, vermindert de aannames bij installatie, updates en het aanmaken van de cache.
Deze pagina bekijkt de implementatie van Laravel Framework v13.36.0 en past de basisbewerkingen van Events toe op het onderhoud van een package op lange termijn. Voor het laden van providers zie je Package discovery, en voor de testomgeving Packages testen.
Listeners van een package expliciet registreren
Verwerking die je package standaard uitvoert, kun je registreren metEvent::listen() in de boot() van een gewone Illuminate\Support\ServiceProvider. De standaardlocatie voor automatische detectie van listeners in Laravel is app/Listeners van de applicatie; src/Listeners binnen een package wordt niet automatisch doorzocht.
Als voorbeeld maken we een package dat een event voor een afgeronde levering logt. Het event is een klasse die alleen de waarden bevat die nodig zijn voor de melding.
handle().
extra.laravel.providers in Composer of voor een expliciete registratie door de gebruiker. Is het event zowel bij HTTP-verwerking als in queue workers nodig, beperk de registratie dan niet met runningInConsole().
Registratie en instantiëring gebeuren op verschillende momenten
Dispatcher::listen() voegt de listener voor een gewone eventnaam toe aan een interne array. Geef je zoals hierboven een klassenaam door, dan wordt de listener op dat moment nog niet geïnstantieerd.
Bij synchrone listeners resolvet createClassCallable() de klasse na het dispatchen van het event via make() van de container. Daardoor kun je dependency injection in de constructor gebruiken.
Deze route voert geen call() van de container uit op handle(). Ontwerp de listener zo dat willekeurige services in de constructor worden geïnjecteerd en handle() het event ontvangt. Ga er niet van uit dat dit hetzelfde mechanisme is als dependency injection in handle() van Artisan-commands.
Wat hier wordt beschreven, geldt voor synchrone listeners. Implementeer je ShouldQueue, dan volgt de listener een aparte route voor de queue. Bekijk in dat geval ook listeners in de queue en Queues voor transacties, nieuwe pogingen en het resolven van afhankelijkheden.
event:cache stopt expliciete registratie niet
event:cache is geen command dat alle bij de event-dispatcher geregistreerde listeners in hun geheel serialiseert.
EventCacheCommand::getEvents() somt Illuminate\Foundation\Support\Providers\EventServiceProvider en de daarvan afgeleide providers op, en slaat per provider het resultaat van de automatische detectie en de mapping uit listens() op. Event::listen() in een gewone ServiceProvider::boot() valt niet onder deze verzameling.
Tegelijkertijd wordt boot() van gewone providers ook uitgevoerd bij een start waarbij een cache aanwezig is. Niet in de cache staan is iets anders dan niet geregistreerd worden wanneer er een cache is.
Je kunt ook
$listen gebruiken in een package dat de Foundation-EventServiceProvider uitbreidt. In de bekeken implementatie heeft de standaardwaarde van shouldDiscoverEvents() echter betrekking op de basisklasse zelf. Alleen het uitbreiden ervan zorgt er niet voor dat de listenermap van je package automatisch wordt gedetecteerd.
Daarnaast worden $subscribe en $observers van deze provider afzonderlijk verwerkt, los van de lus die het resultaat van getEvents() registreert. Concludeer dus niet op basis van alleen de cache van $listen dat ook deze registraties worden overgeslagen.
Dubbele registratie met automatische detectie voorkomen
Voegt de gebruiker de listenermap van het package toe metwithEvents(discover: [...]) en registreert de provider van het package dezelfde listener ook expliciet, dan kan de verwerking voor één event meerdere keren draaien.
Dispatcher::listen() voegt voor gewone events elementen toe aan een array en ontdubbelt dezelfde klassenaam niet automatisch over de hele dispatcher. De array_unique() die de Foundation-EventServiceProvider binnen zijn eigen mapping uitvoert, voegt ook geen expliciete registraties van andere providers samen.
Leg de verantwoordelijkheid voor de registratie bij één partij.
- Registreert het package de standaardlisteners, vraag gebruikers dan niet om die map aan de automatische detectie toe te voegen.
- Kiest de gebruiker de benodigde listeners, dan biedt het package de event- en listenerklassen aan en registreert het dezelfde listeners niet standaard.
- Stap je over van automatische detectie naar expliciete registratie, vermeld dan dat ook de detectie-instellingen aan de kant van de gebruiker en een oude eventcache moeten worden bijgewerkt.
Gedrag voor en na een update controleren
Om de registratiestatus te bekijken, voer jeevent:list uit in een testapplicatie waarin het package is geïnstalleerd. Controleer dat de betreffende listeners zowel zonder als met cache aanwezig zijn.
event:list garandeert niet dat de listener zijn verwerking voltooit of maar één keer wordt uitgevoerd. Voeg daarom ook tests toe die een event echt dispatchen.
Als voorbeeld registreer je CourierServiceProvider in de basis-TestCase van Testbench en controleer je dat de logger precies één keer wordt aangeroepen.
Event::fake() is handig om te controleren of een event is gedispatcht, maar stopt normaal gesproken de uitvoering van de echte listeners. Omdat deze test registratie en verwerking controleert, wordt het hier niet gebruikt. Controleer de combinatie met automatische detectie en een start met cache ook in een aparte testapplicatie en met een nieuwe applicatie-instantie.
Checklist voor onderhoud op lange termijn
- Documenteer eventklassenamen, publieke properties en het registratiebeleid voor listeners als contract voor gebruikers.
- Wijzig je de naam of payload van events waarop gebruikers zich abonneren, communiceer de wijziging dan volgens Versiecompatibiliteit beheren.
- Neem bij updates die de automatische detectie of
$listenwijzigen het opnieuw aanmaken vanevent:cacheop in de deploymentprocedure. - Maak onderscheid tussen de standaardlisteners van het package en eigen listeners van gebruikers, en laat dezelfde standaardlistener niet dubbel registreren.
- Blijf voor elke ondersteunde PHP- en Laravel-versie testen dat listeners precies één keer worden uitgevoerd.