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:
- Registreer een callback bij
afterResolving()van de container. - Als
resolved()true is, haal de service op metmake()en roep de callback ook direct aan.
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 nadatvalidator is geresolved. De officiële ValidationServiceProvider registreert deze sleutel als singleton, en de provider zelf ondersteunt uitgesteld laden.
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. Deresolved($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:
- De nieuwe callback wordt geregistreerd.
- Omdat
resolved()true is, wordtmake()aangeroepen. make()maakt een nieuw object aan en de callback wordt uitgevoerd in het bijbehorende resolutie-event.- Op hetzelfde object dat
make()retourneert, wordt de callback ook direct uitgevoerd.
Gebruik een andere API om objecten te vervangen
De retourwaarde van eenafterResolving-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
- Officiële Laravel-documentatie: Packageontwikkeling
- Officiële Laravel-documentatie: Container events, Extending bindings en Rebinding
- Officiële Laravel-documentatie: Custom validatieregels
- ServiceProvider: callAfterResolving() en het gebruik bij het registreren van resources
- Container: resolved(), resolve() en afterResolving()
- ValidationServiceProvider: singleton-registratie van validator
- Validation Factory: regels registreren met extend()