Skip to main content
Wanneer je vanuit een package functionaliteit toevoegt aan een Laravel-service, wil je soms geen instantie aanmaken totdat de service wordt gebruikt, maar de configuratie wel toepassen als de instantie al bestaat. De methode callAfterResolving() van de service provider is een protected methode die deze twee combineert. Op deze pagina bekijken we de implementatie in Laravel Framework v13.35.0 en duiken we dieper in het uitbreiden vanuit boot() dat in Laravel-packages ontwikkelen wordt behandeld. Het is geen hook die wacht tot de hele applicatie is opgestart, maar een hook op het resolven van een specifieke service.

Wachten als nog niet geresolved, nu uitvoeren als al geresolved

ServiceProvider::callAfterResolving() werkt in twee stappen:
  1. Registreer een callback bij afterResolving() van de container.
  2. Als resolved() true is, haal de service op met make() en roep de callback ook direct aan.
Als de service nog niet geresolved is, roept deze methode zelf geen make() aan op het doel. Bij een normale resolutie bouwt de container het object, past extenders toe, roept de resolving-callbacks aan en daarna pas de afterResolving-callbacks. Bij het normaal ophalen van een singleton retourneert de container vroegtijdig de opgeslagen instantie, dus afterResolving wordt niet bij elke ophaalactie getriggerd. Het belangrijke punt is dat je, als je alleen afterResolving() registreert, de configuratie mist voor singletons die vóór de registratie zijn aangemaakt.

Regels toevoegen aan de validatie-Factory

Als voorbeeld van een package dat een eigen stringregel aanbiedt, registreren we de regel nadat validator is geresolved. De officiële ValidationServiceProvider registreert deze sleutel als singleton, en de provider zelf ondersteunt uitgesteld laden.
In de gebruikende applicatie combineer je de regel met gewone regels.
De extend() in dit voorbeeld is de API voor het registreren van regels van Illuminate\Validation\Factory. Het is een andere methode dan de extend() van de container die verderop aan bod komt. Gewone custom regels worden bij lege waarden soms niet uitgevoerd, dus geef verplichtheid aan met required. Zie Custom validatieregels voor het ontwerp van de regel zelf. Factory::extend() overschrijft het array-element met dezelfde regelnaam, dus als je dezelfde logica opnieuw registreert zoals in dit voorbeeld, komen er geen extra entries bij. Geef publieke regelnamen wel een packagespecifiek voorvoegsel, zodat je geen regels van andere packages overschrijft.
De callback wordt uitgevoerd wanneer de Factory wordt geresolved. De validatieclosure van de regel wordt pas uitgevoerd wanneer een Validator later de betreffende waarde valideert. Bij het registreren van de hook wordt geen invoer gevalideerd.

Zorg dat de doelsleutel en de resolved-controle overeenkomen

Bij de normale resolutie-events van de container worden niet alleen callbacks geselecteerd die overeenkomen met de geregistreerde sleutel, maar ook callbacks die overeenkomen met het type van het opgehaalde object. De resolved($name) die callAfterResolving() direct gebruikt, controleert daarentegen voor de sleutel waarvan de alias is genormaliseerd of er een resolved-vlag of een opgeslagen instantie is. Er wordt niet gezocht in alle aangemaakte objecten. Dat een interface of klasse geresolved is, betekent daarom niet dat resolved() voor een andere sleutel ook altijd true is. Controleer de daadwerkelijke binding en alias van de doelservice en test het al-geresolvede geval met dezelfde sleutel. In het voorbeeld hierboven wordt validator gebruikt, de sleutel die de officiële provider registreert. Daarnaast betekent resolved() ook “is ooit geresolved”. Het betekent niet dat er altijd nog een huidige instantie bestaat.

Geen API die “eenmaal uitvoeren” garandeert

callAfterResolving() laat de callback geregistreerd. Ook nadat hij direct is uitgevoerd, wordt de geregistreerde callback uitgevoerd zodra het object in de toekomst opnieuw wordt geresolved. Roep je de methode nogmaals aan, dan wordt de callback zelf ook nog eens toegevoegd. Wees vooral voorzichtig als een gewone, niet-gedeelde binding al is geresolved. In de onderzochte implementatie gebeurt het volgende:
  1. De nieuwe callback wordt geregistreerd.
  2. Omdat resolved() true is, wordt make() aangeroepen.
  3. make() maakt een nieuw object aan en de callback wordt uitgevoerd in het bijbehorende resolutie-event.
  4. Op hetzelfde object dat make() retourneert, wordt de callback ook direct uitgevoerd.
Via dit pad wordt de zojuist geregistreerde callback twee keer op hetzelfde object toegepast. Hergebruik een ontwerp dat alleen uitgaat van het ophalen van singletons niet zomaar voor gewone bindings.
Verstuur in de callback geen e-mails, roep geen externe API’s aan, voer geen betalingen uit en voeg niet onvoorwaardelijk listeners toe. Beperk het gebruik tot het idempotent toepassen van configuratie op de service, en ontwerp het zo dat bijwerkingen niet dubbel optreden bij herregistratie of herhaald resolven.

Gebruik een andere API om objecten te vervangen

De retourwaarde van een afterResolving-callback wordt niet gebruikt om het object te vervangen dat de container retourneert. Wil je de service zelf vervangen door een decorator te retourneren, overweeg dan de extend() van de container. De closure van die API heeft als contract dat hij de gewijzigde service retourneert. Evenzo is callAfterResolving() geen mechanisme dat alle afhankelijkheden bijwerkt die al in andere objecten zijn opgeslagen. Als je afhankelijkheden wilt bijwerken bij het opnieuw binden, bekijk dan rebinding() in de officiële documentatie en het ontwerp van de betreffende klasse. Zie Uitgestelde service providers voor de vereisten van een provider die services echt uitgesteld laadt. Een hook gebruiken en de provider die de hook registreert zelf uitgesteld laten laden zijn twee verschillende dingen.

Combinaties om te controleren bij updates

Controleer vóór een release van je package niet alleen de normale opstartvolgorde, maar ook het geval waarin een andere provider de service al eerder heeft gebruikt. Als je met een statische vlag bijhoudt dat iets applicatiebreed al eenmaal is gebruikt, kan de configuratie ontbreken bij services die in een nieuwe container of in tests opnieuw zijn aangemaakt. Waarborg idempotentie zoveel mogelijk per doelobject of per geregistreerde sleutel.

Gerelateerde pagina’s

Views van packages overschrijven en bijwerken

Bekijk een voorbeeld van hoe loadViewsFrom() een hook na het resolven gebruikt om een view-namespace te registreren.

Packagevertalingen overschrijven en bijwerken

Bekijk het registreren van namespaces in de Translator en hoe al geladen vertalingen worden behandeld.

Geraadpleegde primaire bronnen

Laatst gewijzigd op 10 oktober 2026