Skip to main content

A proposito di questa pagina

In Fondamenti dello sviluppo di pacchetti abbiamo visto che basta scrivere la sezione extra.laravel di composer.json per registrare automaticamente service provider e facade. In questa pagina spieghiamo cosa succede dietro le quinte, ovvero come funziona la classe Illuminate\Foundation\PackageManifest a livello di codice sorgente.
Questa pagina è la pagina gemella di Fondamenti dello sviluppo di pacchetti. Ti consigliamo di leggere prima l’uso di base dell’auto-discovery.

Visione d’insieme del meccanismo di auto-discovery

La classe PackageManifest

Il cuore dell’auto-discovery è Illuminate\Foundation\PackageManifest. Qui sotto trovi l’implementazione (riassunta) del framework alla versione 13.x.
I punti chiave sono tre.
  • Il manifest, una volta caricato, viene messo in cache in memoria (proprietà $this->manifest). Anche chiamando più volte providers() all’interno di una singola richiesta, l’I/O sul file avviene una sola volta.
  • build() viene eseguito solo quando il file manifest non esiste. In esercizio normale non viene ricostruito ad ogni richiesta.
  • L’oggetto reale è un file che si limita a fare return di un semplice array PHP (bootstrap/cache/packages.php), la forma più veloce da caricare con un semplice require.

Il processo di build del manifest

Il metodo build() è la parte che aggrega effettivamente le informazioni dei composer.json.
Il punto importante è che, invece di fare direttamente il parsing dei composer.json, viene letto vendor/composer/installed.json. Questo è un file di metadati generato da Composer durante composer install / composer update che contiene tutti i pacchetti installati. La sezione extra scritta nei composer.json di ciascun pacchetto è aggregata qui dentro, quindi Laravel legge solo informazioni sotto il controllo di Composer.
installed.json è di solito escluso da git tramite .gitignore, quindi al primo setup (senza la directory vendor/) l’auto-discovery non funziona. La cache viene costruita per la prima volta solo dopo il completamento di composer install.

Le due modalità di dont-discover

dont-discover può essere scritto sia nel composer.json del pacchetto sia in quello dell’applicazione, ma il significato cambia.
composer.json del pacchetto
composer.json dell'applicazione
Osservando l’implementazione di build(), l’array $ignore accumula i configuration['dont-discover'] di ogni pacchetto con array_merge. In altre parole, tecnicamente è possibile che un pacchetto stesso “disabiliti l’auto-discovery per i propri pacchetti dipendenti” (esempio: per evitare doppie registrazioni dei provider di sotto-pacchetti usati internamente). Nell’uso pratico, tuttavia, la disabilitazione avviene di solito lato applicazione.

Specificare * in dont-discover

Se l’array restituito da packagesToIgnore() contiene *, $ignoreAll = true e l’auto-discovery viene disabilitato in blocco per tutti i pacchetti. Utile in CI o in ambienti di test dove si vuole evitare l’overhead dell’auto-discovery, oppure quando si vuole gestire completamente a mano bootstrap/providers.php.

Il file di cache

getCachedPackagesPath() restituisce il valore della variabile d’ambiente APP_PACKAGES_CACHE se presente, altrimenti bootstrap/cache/packages.php.
Se apri direttamente questo file, vedi che si limita a fare return di un semplice array associativo.
Poiché la chiave è il nome del pacchetto, dall’output di php artisan package:discover puoi verificare “quali pacchetti sono stati scoperti”.

Quando la cache viene ricostruita

Illuminate\Foundation\ComposerScripts aggancia tre eventi di Composer, tutti richiamano lo stesso clearCompiled().
Quindi, eseguendo composer install, composer update o composer dump-autoload, la cache di configurazione, servizi e pacchetti viene eliminata in blocco. Al successivo avvio di Laravel viene eseguito PackageManifest::build() che ricostruisce tutto dallo stato più recente di installed.json. Questo è il comportamento standard di un progetto Laravel, registrato negli scripts del suo composer.json.
composer.json dell'app Laravel (estratto)

Ricostruzione manuale con php artisan package:discover

Se la cache è rimasta obsoleta, oppure se hai modificato direttamente vendor/ senza passare da Composer, puoi ricostruire manualmente con il comando package:discover.
L’implementazione di questo comando è un wrapper molto sottile.
Si limita a chiamare $manifest->build() e a stampare il risultato: non c’è quasi nessuna logica specifica del comando. In situazioni in cui gli eventi di Composer non vengono scatenati — ad esempio quando in una pipeline CI usi composer install --no-scripts — devi invocare esplicitamente questo comando.
Quando testi i pacchetti con Orchestra Testbench, Testbench fornisce il proprio comando vendor/bin/testbench package:discover. Per i dettagli vedi Test dei pacchetti con Testbench. È diverso dal package:discover di Artisan e costruisce il manifest per l’app scheletro dedicata a Testbench.

Note per il deploy

In produzione è comune eseguire composer install --no-dev --optimize-autoloader, ma se aggiungi --no-scripts la cache dei pacchetti non viene aggiornata. È più sicuro inserire uno step di ricostruzione esplicito nello script di deploy.
Anche l’ordine è importante. Esegui package:discover prima di config:cache. Se la cache di configurazione viene creata per prima, le configurazioni dei pacchetti aggiunte successivamente (ad esempio quelle registrate tramite mergeConfigFrom) potrebbero non essere riflesse.
  • L’auto-discovery non si basa sul contenuto statico dei composer.json, ma legge il vendor/composer/installed.json generato da Composer.
  • Il risultato viene messo in cache come semplice array PHP in bootstrap/cache/packages.php e caricato rapidamente con un semplice require.
  • La cache viene eliminata automaticamente dagli eventi composer install/update/dump-autoload e ricostruita al successivo avvio.
  • Negli ambienti in cui Composer viene eseguito con --no-scripts devi chiamare esplicitamente php artisan package:discover.
  • Specificando * in dont-discover puoi disabilitare l’intero auto-discovery.

Pagine correlate

Ultima modifica il 2 agosto 2026