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

# Hook di risoluzione dei servizi nei pacchetti

> Analizza callAfterResolving() di Laravel 13 e spiega come estendere servizi non ancora risolti o già risolti, con le avvertenze su singleton, binding normali e nuove registrazioni.

Quando un pacchetto aggiunge funzionalità a un servizio di Laravel, può essere utile non creare l'istanza finché non viene usata e, allo stesso tempo, applicare la configurazione anche se l'istanza è già stata creata. Il metodo protected `callAfterResolving()` del service provider serve proprio a combinare questi due comportamenti.

Questa pagina esamina l'implementazione di Laravel Framework `v13.35.0` e approfondisce l'estensione da `boot()` descritta in [Sviluppo di pacchetti Laravel](/it/advanced/package-development). Non si tratta di un hook che attende il completamento dell'avvio dell'intera applicazione, ma di un hook sulla risoluzione di un servizio specifico.

## Attendere se non risolto, eseguire subito se già risolto

`ServiceProvider::callAfterResolving()` esegue due passaggi.

1. Registra la callback in `afterResolving()` del container.
2. Se `resolved()` è true, ottiene il servizio con `make()` e invoca la callback anche immediatamente.

Se il servizio non è ancora stato risolto, il metodo stesso non esegue `make()` sul servizio. In una risoluzione normale, il container costruisce l'oggetto, applica gli extender, invoca le callback `resolving` e infine le callback `afterResolving`.

```mermaid theme={null}
flowchart TD
    A["callAfterResolving() in boot()"] --> B["Registrazione in afterResolving"]
    B --> C{"Il servizio è resolved()?"}
    C -->|No| D["Il servizio non viene creato ora"]
    D --> E["Il servizio viene risolto in seguito"]
    E --> F["Esecuzione della callback registrata"]
    C -->|Sì| G["Recupero del servizio con make()"]
    G --> H["Esecuzione immediata della callback"]
```

| Metodo | Non risolto al momento della registrazione | Singleton già risolto al momento della registrazione |
| - | - | - |
| Configurazione diretta dopo `$this->app->make()` | Lo crea subito | Configura l'istanza esistente |
| `$this->app->afterResolving()` | Attende le risoluzioni future | La sola registrazione non configura l'istanza esistente |
| `$this->callAfterResolving()` | Attende le risoluzioni future | Configura subito anche l'istanza esistente |

Nel normale recupero di un singleton, il container restituisce anticipatamente l'istanza salvata, quindi `afterResolving` non viene attivato a ogni recupero. Il punto importante è che registrando semplicemente `afterResolving()` si perde la configurazione dei singleton creati prima della registrazione.

## Aggiungere una regola alla Factory di validazione

Come esempio di un pacchetto che fornisce una propria regola per stringhe, registriamo la regola dopo la risoluzione di `validator`. Il `ValidationServiceProvider` ufficiale registra questa chiave come singleton e il provider stesso supporta il caricamento differito.

```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.',
            );
        });
    }
}
```

Nell'applicazione che utilizza il pacchetto, la regola si combina con le regole normali.

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

In questo esempio `extend()` è l'API di registrazione delle regole di `Illuminate\Validation\Factory`, ed è un metodo diverso dall'`extend()` del container descritto più avanti. Poiché le normali regole personalizzate possono non essere eseguite con valori vuoti, l'obbligatorietà va indicata con `required`. Per la progettazione dettagliata delle regole, consulta [Regole di validazione personalizzate](/it/advanced/custom-validation-rules).

`Factory::extend()` sovrascrive l'elemento dell'array con lo stesso nome di regola, quindi registrare di nuovo la stessa logica, come in questo esempio, non aggiunge voci. Tuttavia, per non sovrascrivere le regole di altri pacchetti, aggiungi un prefisso specifico del pacchetto ai nomi delle regole che esponi.

<Info>
  La callback viene eseguita quando la Factory viene risolta. La closure di verifica della regola viene eseguita più tardi, quando il Validator valida il valore. La registrazione dell'hook non valida alcun input.
</Info>

## Allineare la chiave di destinazione e il controllo di risoluzione

Negli eventi di risoluzione normali del container, vengono selezionate non solo le callback che corrispondono alla chiave registrata, ma anche quelle che corrispondono al tipo dell'oggetto ottenuto. Invece, `resolved($name)`, usato immediatamente da `callAfterResolving()`, verifica se per la chiave normalizzata rispetto agli alias esiste un flag di risoluzione o un'istanza salvata. Non effettua una ricerca su tutti gli oggetti già creati.

Per questo, il fatto che un'interfaccia o una classe sia già stata risolta non garantisce che `resolved()` restituisca true anche per un'altra chiave. Verifica il binding e gli alias effettivi del servizio di destinazione e testa anche il caso già risolto con la stessa chiave. Nell'esempio precedente si specifica `validator`, registrato dal provider ufficiale.

Inoltre, `resolved()` include anche il caso "risolto in passato". Non significa che l'istanza corrente sia necessariamente ancora presente.

## Non è un'API che garantisce un'esecuzione "una sola volta"

`callAfterResolving()` lascia la callback registrata. Anche dopo l'esecuzione immediata, la callback registrata verrà eseguita ogni volta che l'oggetto viene risolto di nuovo in futuro. Inoltre, chiamando di nuovo il metodo si aggiunge un'altra callback.

Fai particolare attenzione se un binding normale non condiviso è già stato risolto. Nell'implementazione esaminata accade quanto segue.

1. Viene registrata la nuova callback.
2. Poiché `resolved()` è true, viene chiamato `make()`.
3. `make()` crea un nuovo oggetto e la callback viene eseguita nel relativo evento di risoluzione.
4. La callback immediata viene eseguita anche sullo stesso oggetto restituito da `make()`.

In questo percorso, la callback appena registrata viene applicata due volte allo stesso oggetto. Non riutilizzare così com'è con i binding normali un design pensato solo per il recupero di singleton.

<Warning>
  Non inviare email, chiamare API esterne, effettuare addebiti o aggiungere listener senza condizioni all'interno della callback. Limitane l'uso all'applicazione idempotente della configurazione al servizio, in modo che nuove registrazioni o nuove risoluzioni non duplichino gli effetti collaterali.
</Warning>

## Usare un'altra API per sostituire l'oggetto

Il valore restituito dalla callback `afterResolving` non viene usato per sostituire l'oggetto restituito dal container. Se vuoi restituire un decorator e sostituire il servizio stesso, valuta l'`extend()` del container. Il contratto della closure di questa API prevede che restituisca il servizio modificato.

Allo stesso modo, `callAfterResolving()` non è un meccanismo che aggiorna tutte le dipendenze già salvate in altri oggetti. Se lo scopo è aggiornare le dipendenze al momento di un nuovo binding, consulta `rebinding()` nella documentazione ufficiale e la progettazione della classe interessata.

Per i requisiti di un provider che carichi davvero i servizi in modo differito, consulta [DeferrableProvider](/it/advanced/deferred-provider). Usare un hook e rendere differito il provider che registra quell'hook sono due cose distinte.

## Combinazioni da verificare durante gli aggiornamenti

Prima di rilasciare il pacchetto, verifica non solo il normale ordine di avvio, ma anche il caso in cui un altro provider abbia usato il servizio in precedenza.

| Caso | Cosa verificare |
| - | - |
| Hook registrato con il servizio non ancora risolto | La sola registrazione non crea il servizio e la configurazione viene applicata alla prima risoluzione |
| Registrazione dopo aver risolto il singleton | La configurazione viene applicata subito alla stessa istanza |
| Nuovo recupero del singleton configurato con un normale `make()` | Viene restituita la stessa istanza e le callback di risoluzione non vengono eseguite più volte |
| Registrazione su un binding normale risolto in passato | Nulla si rompe anche con la doppia applicazione, dal `make()` della registrazione e dalla chiamata esplicita |
| Più registrazioni dell'hook o ricreazione dell'istanza | Regole, listener, percorsi e simili non si accumulano involontariamente |
| Aggiornamento della versione di Laravel supportata | Ricontrollare chiavi di binding, condivisione e percorso di esecuzione dell'hook |

Se registri con un flag statico che l'hook è stato usato una sola volta nell'intera applicazione, la configurazione potrebbe mancare nei servizi ricreati in un nuovo container o nei test. Per quanto possibile, garantisci l'idempotenza della configurazione a livello del singolo oggetto di destinazione o della chiave registrata.

## Pagine correlate

<Columns cols={2}>
  <Card title="Sovrascrivere e aggiornare le view di un pacchetto" icon="eye" href="/it/advanced/package-views">
    Un esempio di come loadViewsFrom() usa un hook post-risoluzione per registrare il namespace delle view.
  </Card>

  <Card title="Sovrascrittura e aggiornamento delle traduzioni di un pacchetto" icon="language" href="/it/advanced/package-translations">
    La registrazione del namespace nel Translator e la gestione delle traduzioni già caricate.
  </Card>
</Columns>

## Fonti primarie consultate

* [Documentazione ufficiale di Laravel: sviluppo di pacchetti](https://github.com/laravel/docs/blob/13.x/packages.md)
* [Documentazione ufficiale di Laravel: Container events, Extending bindings, Rebinding](https://github.com/laravel/docs/blob/13.x/container.md#container-events)
* [Documentazione ufficiale di Laravel: regole di validazione personalizzate](https://github.com/laravel/docs/blob/13.x/validation.md#custom-validation-rules)
* [ServiceProvider: callAfterResolving() e uso nella registrazione delle risorse](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Support/ServiceProvider.php)
* [Container: resolved(), resolve(), afterResolving()](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Container/Container.php)
* [ValidationServiceProvider: registrazione singleton di validator](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Validation/ValidationServiceProvider.php)
* [Validation Factory: registrazione delle regole con extend()](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Validation/Factory.php)


## Related topics

- [Sviluppo di pacchetti Laravel](/it/advanced/package-development.md)
- [Argomenti avanzati](/it/advanced/index.md)
- [Analisi statica dei pacchetti (PHPStan / Larastan)](/it/advanced/package-static-analysis.md)
- [Service provider differiti](/it/advanced/deferred-provider.md)
- [Merge e cache della configurazione dei pacchetti](/it/advanced/package-config-merging.md)


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