> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Hooks na het resolven van packageservices

> Een analyse van callAfterResolving() in Laravel 13: hoe je nog niet en al wel geresolvede services uitbreidt, en waar je op moet letten bij singletons, gewone bindings en herhaalde registratie.

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](/nl/advanced/package-development) 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.

```mermaid theme={null}
flowchart TD
    A["callAfterResolving() in boot()"] --> B["Registreren bij afterResolving"]
    B --> C{"Is het doel resolved()?"}
    C -->|Nee| D["Doel nu niet aanmaken"]
    D --> E["Doel wordt later geresolved"]
    E --> F["Geregistreerde callback uitvoeren"]
    C -->|Ja| G["Doel ophalen met make()"]
    G --> H["Callback ook direct uitvoeren"]
```

| Aanpak | Nog niet geresolved bij registratie | Singleton al geresolved bij registratie |
| - | - | - |
| Direct configureren via `$this->app->make()` | Wordt direct aangemaakt | Configureert de bestaande instantie |
| `$this->app->afterResolving()` | Wacht op toekomstige resoluties | Alleen registreren configureert de bestaande instantie niet |
| `$this->callAfterResolving()` | Wacht op toekomstige resoluties | Configureert ook de bestaande instantie direct |

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.

```php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Factory;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->callAfterResolving('validator', function (Factory $factory): void {
            $factory->extend(
                'courier_tracking_code',
                static function ($attribute, $value, $parameters, $validator): bool {
                    return is_string($value)
                        && preg_match('/\ACR-[0-9]{8}\z/', $value) === 1;
                },
                'The :attribute must be a valid courier tracking code.',
            );
        });
    }
}
```

In de gebruikende applicatie combineer je de regel met gewone regels.

```php theme={null}
$request->validate([
    'tracking_code' => ['required', 'string', 'courier_tracking_code'],
]);
```

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](/nl/advanced/custom-validation-rules) 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.

<Info>
  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.
</Info>

## 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.

<Warning>
  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.
</Warning>

## 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](/nl/advanced/deferred-provider) 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.

| Geval | Wat je controleert |
| - | - |
| Hook registreren terwijl het doel nog niet geresolved is | Registreren alleen maakt het doel niet aan, en de configuratie wordt bij de eerste resolutie toegepast |
| Singleton eerst resolven en daarna registreren | De configuratie wordt direct op dezelfde instantie toegepast |
| Geconfigureerde singleton opnieuw ophalen met een normale `make()` | Dezelfde instantie wordt geretourneerd en resolutie-callbacks worden niet dubbel uitgevoerd |
| Registreren op een eerder geresolvede gewone binding | Niets gaat stuk, ook niet bij dubbele toepassing door `make()` bij registratie en de expliciete aanroep |
| Hook meerdere keren registreren of instanties opnieuw aanmaken | Dezelfde regels, listeners, paden enzovoort stapelen zich niet onbedoeld op |
| Ondersteunde Laravel-versie bijwerken | Bindingsleutels, gedeeldheid en het uitvoeringspad van hooks opnieuw controleren |

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

<Columns cols={2}>
  <Card title="Views van packages overschrijven en bijwerken" icon="eye" href="/nl/advanced/package-views">
    Bekijk een voorbeeld van hoe loadViewsFrom() een hook na het resolven gebruikt om een view-namespace te registreren.
  </Card>

  <Card title="Packagevertalingen overschrijven en bijwerken" icon="language" href="/nl/advanced/package-translations">
    Bekijk het registreren van namespaces in de Translator en hoe al geladen vertalingen worden behandeld.
  </Card>
</Columns>

## Geraadpleegde primaire bronnen

* [Officiële Laravel-documentatie: Packageontwikkeling](https://github.com/laravel/docs/blob/13.x/packages.md)
* [Officiële Laravel-documentatie: Container events, Extending bindings en Rebinding](https://github.com/laravel/docs/blob/13.x/container.md#container-events)
* [Officiële Laravel-documentatie: Custom validatieregels](https://github.com/laravel/docs/blob/13.x/validation.md#custom-validation-rules)
* [ServiceProvider: callAfterResolving() en het gebruik bij het registreren van resources](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Support/ServiceProvider.php)
* [Container: resolved(), resolve() en afterResolving()](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Container/Container.php)
* [ValidationServiceProvider: singleton-registratie van validator](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Validation/ValidationServiceProvider.php)
* [Validation Factory: regels registreren met extend()](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Validation/Factory.php)


## Related topics

- [Laravel-packages ontwikkelen](/nl/advanced/package-development.md)
- [Geavanceerde onderwerpen](/nl/advanced/index.md)
- [Session hooks](/nl/packages/laravel-copilot-sdk/hooks.md)
- [⚡Introductie van Livewire 4 — reactieve UI's bouwen zonder JavaScript](/nl/blog/livewire-introduction.md)
- [Eerste verkenning van Laravel Passkeys (passkeys-server + @laravel/passkeys)](/nl/blog/passkeys-introduction.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.