Passer au contenu principal

Qu’est-ce que GeneratorCommand

Illuminate\Console\GeneratorCommand est la classe abstraite qui sert de base à toutes les commandes de génération de code de Laravel. make:model, make:controller, make:request, etc. héritent tous de cette classe. Lorsque vous proposez une commande make:xxx personnalisée dans votre package, il suffit à l’utilisateur d’exécuter par exemple php artisan make:handler OrderHandler au lieu de créer la classe manuellement, et un fichier avec le namespace correct est généré.
GeneratorCommand n’est presque pas documenté officiellement : il faut lire directement le code source du framework pour le comprendre. C’est un sujet avancé typique.

Implémentation minimale

Dans une classe qui hérite de GeneratorCommand, seule la méthode getStub() est obligatoire. Les autres propriétés sont facultatives, mais en pratique on définit généralement les éléments suivants.
MembreTypeRôle
$namepropriétéNom de la commande (ex. : make:handler)
$descriptionpropriétéDescription de la commande
$typepropriétéNom du type d’élément généré. Utilisé dans le message de succès (ex. : Handler)
getStub()méthode (obligatoire)Renvoie le chemin du fichier stub
getDefaultNamespace()méthodeContrôle le namespace par défaut de destination
Voici un exemple d’implémentation de la commande make:handler.
<?php

namespace Vendor\Package\Console\Commands;

use Illuminate\Console\GeneratorCommand;

class HandlerMakeCommand extends GeneratorCommand
{
    protected $name = 'make:handler';

    protected $description = 'Create a new handler class';

    protected $type = 'Handler';

    protected function getStub(): string
    {
        return __DIR__.'/stubs/handler.stub';
    }

    protected function getDefaultNamespace($rootNamespace): string
    {
        return $rootNamespace.'\Handlers';
    }
}
Lorsque getDefaultNamespace() est configuré ainsi, exécuter php artisan make:handler OrderHandler génère la classe App\Handlers\OrderHandler dans app/Handlers/OrderHandler.php.

Créer le fichier stub

Placez le fichier stub au chemin renvoyé par getStub(). Un stub est un fichier PHP servant de modèle ; ses espaces réservés sont remplacés par le namespace et le nom de la classe.
src
Console
Commands
HandlerMakeCommand.php
stubs
handler.stub
Exemple de fichier stub :
handler.stub
<?php

namespace {{ namespace }};

class {{ class }}
{
    public function handle(): void
    {
        //
    }
}
GeneratorCommand remplace automatiquement les espaces réservés suivants dans le stub.
Espace réservéValeur de remplacementNotation alternative
{{ namespace }}Namespace de la classe généréeDummyNamespace
{{ class }}Nom de la classe généréeDummyClass
{{ rootNamespace }}Namespace racine de l’applicationDummyRootNamespace
{{ namespace }} et DummyNamespace produisent le même résultat. Les stubs intégrés à Laravel incluaient les deux formes, mais pour toute nouvelle création, la forme {{ namespace }} est recommandée.

Permettre la personnalisation des stubs

Pour offrir un mécanisme permettant aux utilisateurs de remplacer les stubs, utilisez le pattern resolveStubPath(). Publiez d’abord les stubs dans le boot() du service provider.
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->publishes([
            __DIR__.'/../Console/Commands/stubs' => base_path('stubs'),
        ], 'stubs');
    }
}
Ensuite, dans getStub(), donnez la priorité au stub personnalisé par l’utilisateur.
protected function getStub(): string
{
    return $this->resolveStubPath('/stubs/handler.stub');
}

protected function resolveStubPath(string $stub): string
{
    return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
        ? $customPath
        : __DIR__.$stub;
}
Un utilisateur qui exécute php artisan vendor:publish --tag=stubs peut alors éditer stubs/handler.stub à la racine du projet pour modifier le modèle.
resolveStubPath() est également le pattern utilisé par RequestMakeCommand intégré à Laravel. Si vous publiez un package, adoptez ce pattern.

Enregistrement dans le service provider

Enregistrez la commande dans la méthode boot() du service provider. En vérifiant runningInConsole(), vous évitez tout chargement inutile lors des requêtes web.
<?php

namespace Vendor\Package;

use Illuminate\Support\ServiceProvider;
use Vendor\Package\Console\Commands\HandlerMakeCommand;

class PackageServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        if ($this->app->runningInConsole()) {
            $this->commands([
                HandlerMakeCommand::class,
            ]);

            $this->publishes([
                __DIR__.'/../Console/Commands/stubs' => base_path('stubs'),
            ], 'stubs');
        }
    }
}
En configurant extra.laravel dans le composer.json du package, vous évitez à l’utilisateur d’avoir à enregistrer le service provider manuellement.
"extra": {
    "laravel": {
        "providers": [
            "Vendor\\Package\\PackageServiceProvider"
        ]
    }
}

Cas d’utilisation

Voici quelques cas d’usage où GeneratorCommand fait briller ses atouts.
Une commande qui génère des Request héritant d’une classe de base propre incluant des vérifications d’authentification ou une logique de validation personnalisée. getDefaultNamespace() renvoie App\Http\Requests.
Une commande qui génère le boilerplate d’un Data Transfer Object. Prévoyez un stub avec des propriétés readonly et une méthode factory from().
Une commande qui génère des classes Action à responsabilité unique. Elle crée dans le namespace App\Actions des classes dotées d’une méthode execute().
La commande make:livewire est implémentée dans la classe MakeCommand qui hérite de GeneratorCommand. Elle surcharge handle() pour générer simultanément la classe du composant et la vue Blade.

Tests

Utilisez Orchestra Testbench pour vérifier que la commande génère correctement les fichiers.
<?php

namespace Tests\Feature\Console;

use Illuminate\Support\Facades\File;
use Orchestra\Testbench\TestCase;
use Vendor\Package\PackageServiceProvider;

class HandlerMakeCommandTest extends TestCase
{
    protected function getPackageProviders($app): array
    {
        return [PackageServiceProvider::class];
    }

    protected function tearDown(): void
    {
        File::deleteDirectory(app_path('Handlers'));

        parent::tearDown();
    }

    public function test_make_handler_creates_file(): void
    {
        $path = app_path('Handlers/OrderHandler.php');

        $this->artisan('make:handler', ['name' => 'OrderHandler'])
            ->assertSuccessful();

        $this->assertFileExists($path);
        $this->assertStringContainsString('namespace App\Handlers;', File::get($path));
        $this->assertStringContainsString('class OrderHandler', File::get($path));
    }

    public function test_make_handler_does_not_overwrite_existing_file(): void
    {
        $path = app_path('Handlers/OrderHandler.php');
        File::ensureDirectoryExists(dirname($path));
        File::put($path, '<?php // existing');

        $this->artisan('make:handler', ['name' => 'OrderHandler'])
            ->assertFailed();
    }
}
Les commandes Generator écrivent sur le système de fichiers réel. Nettoyez impérativement dans tearDown(). Cela garantit l’exécution du nettoyage même si le test échoue en cours de route.

Pages associées

Développement de packages Laravel

Découvrez les bases du développement de packages avec les service providers.

Tester des packages Laravel avec Orchestra Testbench

Découvrez comment mettre en place l’infrastructure de test d’un package.
Dernière modification le 13 juillet 2026