Skip to main content
Quando vuoi aggiungere al pacchetto comandi Artisan per diagnostica, sincronizzazione o installazione, considera separatamente la registrazione del comando, la creazione dell’istanza e l’esecuzione dell’elaborazione. Se risolvi nel costruttore servizi necessari solo in fase di esecuzione, rischi di coinvolgere anche l’avvio di comandi Artisan che non c’entrano nulla. Questa pagina esamina l’implementazione di Laravel Framework v13.35.0 e approfondisce l’esempio di registrazione con commands() presentato in Sviluppo di pacchetti Laravel. Per l’implementazione della generazione di file consulta GeneratorCommand, e per la partecipazione ai task di ottimizzazione consulta Integrazione con optimize.

Registrare esplicitamente dal provider

I comandi di un pacchetto si registrano tramite il nome della classe nel metodo boot() del service provider. Il rilevamento automatico della directory app/Console/Commands dell’applicazione e la registrazione delle classi fornite da un pacchetto sono due punti di ingresso distinti.
Questo esempio presuppone che il provider venga caricato tramite il package auto-discovery o tramite una registrazione esplicita lato applicazione. Non basta inserire una classe di comando perché il provider del pacchetto venga registrato automaticamente. runningInConsole() verifica se ci si trova in un ambiente console, non se è in esecuzione un comando specifico. Se prevedi anche l’uso tramite Artisan::call() all’interno di una richiesta HTTP, tieni conto che questa condizione potrebbe impedire la registrazione e definisci il contratto d’uso valutando anche una registrazione incondizionata. Per l’esecuzione da codice consulta Artisan.

commands() non esegue il comando immediatamente

ServiceProvider::commands() registra in Illuminate\Console\Application::starting() una closure che utilizza i nomi di classe ricevuti. In questo momento il metodo handle() del comando non viene chiamato. Con il normale Console Kernel, i callback di avvio registrati vengono eseguiti in seguito, quando viene creata l’Artisan Application. A quel punto resolveCommands() passa ogni classe a resolve() e procede con la registrazione dei comandi. Il punto fondamentale è che la creazione dell’istanza di un comando non coincide necessariamente con la sua esecuzione. Per le classi normali che non seguono il percorso di registrazione differita dedicato descritto più avanti, resolve() chiama make() del container, quindi il costruttore e le sue dipendenze vengono risolti al momento della registrazione. Di conseguenza, anche solo eseguire php artisan list o un altro comando può far partire il costruttore del comando del pacchetto. Collocare commands() in boot() non garantisce di per sé che la creazione dell’istanza venga rimandata fino all’esecuzione.

Iniettare le dipendenze di esecuzione in handle()

Come esempio, creiamo un comando che mostra soltanto se la configurazione del pacchetto è abilitata o disabilitata. Come nella documentazione ufficiale di Artisan per Laravel 13, nome e descrizione vengono definiti con gli attributi Signature e Description.
In questo esempio non viene aggiunto un costruttore e il Repository della configurazione viene ricevuto come argomento di handle(). Poiché nel percorso di esecuzione del comando Command::execute() usa call() del container, le dipendenze tipizzate vengono iniettate. Anche quando usi un client per API esterne o un servizio di sincronizzazione, puoi iniettarlo nella stessa posizione se serve solo in fase di esecuzione. Tuttavia, se la creazione del servizio stesso o il boot() di un altro provider hanno effetti collaterali, questi non vengono evitati automaticamente.
Nel costruttore non eseguire connessioni ad API esterne, aggiornamenti del database o sovrascritture di file pubblicati. Gli utenti del pacchetto devono poter usare list e help anche subito dopo l’installazione o quando la configurazione della connessione non è ancora completa.
Se definisci un costruttore personalizzato, chiama anche parent::__construct(). Il costruttore padre di Laravel, infatti, configura il comando a partire da attributi, signature, description e così via.

Signature e registrazione differita sono meccanismi distinti

Il metodo Application::resolve() esaminato contiene un ramo che legge il name dell’attributo Symfony AsCommand e salva la corrispondenza tra nome e classe in una command map. In questo ramo make() del container non viene chiamato subito. Il Console Kernel chiama poi setContainerCommandLoader() per configurare un loader che usa questa map. L’attributo Laravel Signature usato nell’esempio precedente, invece, è separato da questa verifica di AsCommand. Aggiungere Signature non basta perché la classe segua questo percorso di registrazione differita. Considera questa differenza come un aspetto a cui prestare attenzione quando leggi l’implementazione interna e, prima di tutto, riduci il costo di creazione e gli effetti collaterali con la definizione ufficiale dei comandi e la dependency injection in handle(). Anche in presenza di un loader differito, le informazioni del comando possono essere necessarie per l’elenco, l’aiuto e così via: quindi non progettare partendo dal presupposto che il comando “non venga mai creato se non durante la sua esecuzione”.

Non rimandare la registrazione dei comandi

Caricare in modo differito i binding dei servizi e far conoscere un comando ad Artisan sono due cose diverse. Se un provider implementa DeferrableProvider, il suo stesso boot() potrebbe non essere eseguito finché il servizio interessato non diventa necessario. Se la registrazione dei comandi si trova solo in quel boot() e il provider non viene caricato prima dell’avvio di Artisan, non viene registrato nemmeno il callback di avvio che segnala l’esistenza del comando. Anche se un servizio spostato nella dependency injection di handle() carica il provider differito, questo non risolve il problema che si presenta prima che Artisan trovi il comando. Per garantire l’esposizione dei comandi, puoi collocare la registrazione in un provider caricato immediatamente e isolare solo i binding dei servizi pesanti in un provider differito separato. Per i requisiti specifici consulta Service provider differiti.

Cosa verificare negli aggiornamenti

Nome del comando, argomenti, opzioni, output e codice di uscita sono un’interfaccia pubblica usata dagli script shell e dalla CI degli utenti. Non modificarli con la stessa leggerezza con cui modifichi l’implementazione interna di una classe: verifica la compatibilità e la procedura di migrazione. Per lo StatusCommand precedente, puoi verificare output e codice di uscita come segue in un ambiente di test che carica il provider. Per l’infrastruttura di test consulta Testare pacchetti Laravel con Orchestra Testbench, e per i dettagli sulle assertion consulta Test da console.
Inoltre, per i comandi che usano servizi pesanti, verifica anche che i metodi di business del servizio non vengano chiamati durante l’esecuzione dell’elenco o dell’aiuto. Verificare soltanto che la registrazione funzioni non permette di rilevare l’impatto su comandi non correlati.

Fonti primarie consultate

Ultima modifica il 12 ottobre 2026