A proposito di questa pagina
In Fondamenti dello sviluppo di pacchetti abbiamo visto che basta scrivere la sezioneextra.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.
- Il manifest, una volta caricato, viene messo in cache in memoria (proprietà
$this->manifest). Anche chiamando più volteproviders()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
returndi un semplice array PHP (bootstrap/cache/packages.php), la forma più veloce da caricare con un semplicerequire.
Il processo di build del manifest
Il metodobuild() è la parte che aggrega effettivamente le informazioni dei composer.json.
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
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.
return di un semplice array associativo.
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().
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.
$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.
Note per il deploy
In produzione è comune eseguirecomposer 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.
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.
Riepilogo
- L’auto-discovery non si basa sul contenuto statico dei
composer.json, ma legge ilvendor/composer/installed.jsongenerato da Composer. - Il risultato viene messo in cache come semplice array PHP in
bootstrap/cache/packages.phpe caricato rapidamente con un semplicerequire. - La cache viene eliminata automaticamente dagli eventi
composer install/update/dump-autoloade ricostruita al successivo avvio. - Negli ambienti in cui Composer viene eseguito con
--no-scriptsdevi chiamare esplicitamentephp artisan package:discover. - Specificando
*indont-discoverpuoi disabilitare l’intero auto-discovery.
Pagine correlate
- Fondamenti dello sviluppo di pacchetti — uso di base di service provider e
extra.laravel - Service provider differiti — ottimizzare quando i provider scoperti vengono caricati
- Test dei pacchetti con Orchestra Testbench — il comando
package:discoverspecifico di Testbench