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

# GeneratorCommand — eigen make: commando's implementeren

> Leer hoe je Illuminate\Console\GeneratorCommand extendt om een eigen make: commando voor je pakket te maken. Van het aanmaken van stub-bestanden tot het beheren van namespaces, praktisch uitgelegd.

## Wat is GeneratorCommand

`Illuminate\Console\GeneratorCommand` is de abstracte basisklasse voor alle codegeneratiecommando's van Laravel. `make:model`, `make:controller`, `make:request` en dergelijke extenden allemaal deze klasse.

```mermaid theme={null}
flowchart TD
    A["GeneratorCommand<br>(abstracte klasse)"] --> B["make:model<br>ModelMakeCommand"]
    A --> C["make:request<br>RequestMakeCommand"]
    A --> D["make:controller<br>ControllerMakeCommand"]
    A --> E["make:handler<br>jouw commando"]
```

Als je pakket een eigen `make:xxx` commando aanbiedt, hoeven gebruikers klassen niet meer handmatig aan te maken: ze voeren gewoon iets als `php artisan make:handler OrderHandler` uit en er wordt een bestand met de juiste namespace gegenereerd.

<Info>
  `GeneratorCommand` staat nauwelijks in de officiële documentatie; je begrijpt hem pas als je de broncode van het framework zelf leest. Een typisch gevorderd onderwerp.
</Info>

## Minimale implementatie

Een klasse die `GeneratorCommand` extendt, hoeft alleen de methode `getStub()` te implementeren. De overige properties zijn optioneel, maar in de praktijk stel je het volgende in.

| Lid                     | Soort               | Rol                                                                                           |
| ----------------------- | ------------------- | --------------------------------------------------------------------------------------------- |
| `$name`                 | Property            | Naam van het commando (bijv. `make:handler`)                                                  |
| `$description`          | Property            | Beschrijving van het commando                                                                 |
| `$type`                 | Property            | Typenaam van het gegenereerde artefact; wordt gebruikt in het succesbericht (bijv. `Handler`) |
| `getStub()`             | Methode (verplicht) | Geeft het pad naar het stub-bestand terug                                                     |
| `getDefaultNamespace()` | Methode             | Bepaalt de standaard-namespace van het gegenereerde bestand                                   |

Hier een voorbeeld van de implementatie van een `make:handler` commando.

```php theme={null}
<?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';
    }
}
```

Met `getDefaultNamespace()` ingesteld wordt bij het uitvoeren van `php artisan make:handler OrderHandler` de klasse `App\Handlers\OrderHandler` gegenereerd in `app/Handlers/OrderHandler.php`.

## Een stub-bestand maken

Plaats een stub-bestand op het pad dat `getStub()` teruggeeft. Een stub is een PHP-bestand dat als template dient; de placeholders worden vervangen door de namespace en de klassenaam.

<Tree>
  <Tree.Folder name="src" defaultOpen>
    <Tree.Folder name="Console" defaultOpen>
      <Tree.Folder name="Commands" defaultOpen>
        <Tree.File name="HandlerMakeCommand.php" />

        <Tree.Folder name="stubs" defaultOpen>
          <Tree.File name="handler.stub" />
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
  </Tree.Folder>
</Tree>

Voorbeeld van een stub-bestand:

```php handler.stub theme={null}
<?php

namespace {{ namespace }};

class {{ class }}
{
    public function handle(): void
    {
        //
    }
}
```

`GeneratorCommand` vervangt automatisch de volgende placeholders in de stub.

| Placeholder           | Vervangen door                       | Alternatieve notatie |
| --------------------- | ------------------------------------ | -------------------- |
| `{{ namespace }}`     | Namespace van de gegenereerde klasse | `DummyNamespace`     |
| `{{ class }}`         | Naam van de gegenereerde klasse      | `DummyClass`         |
| `{{ rootNamespace }}` | Root-namespace van de app            | `DummyRootNamespace` |

`{{ namespace }}` en `DummyNamespace` geven allebei hetzelfde resultaat. De ingebouwde stubs van Laravel bevatten beide vormen, maar voor nieuwe stubs wordt de vorm `{{ namespace }}` aanbevolen.

## Aanpasbare stubs mogelijk maken

Om gebruikers de mogelijkheid te geven stubs te overschrijven, gebruik je het `resolveStubPath()`-patroon. Publiceer eerst de stubs in de `boot()` van je service provider.

```php theme={null}
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->publishes([
            __DIR__.'/../Console/Commands/stubs' => base_path('stubs'),
        ], 'stubs');
    }
}
```

Laat vervolgens `getStub()` voorrang geven aan de door de gebruiker aangepaste stub.

```php theme={null}
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;
}
```

Gebruikers die `php artisan vendor:publish --tag=stubs` uitvoeren, kunnen de template aanpassen door `stubs/handler.stub` in de projectroot te bewerken.

<Tip>
  `resolveStubPath()` is een patroon dat ook in Laravels ingebouwde `RequestMakeCommand` wordt gebruikt. Neem dit patroon over als je een pakket publiceert.
</Tip>

## Registreren in de service provider

Commando's registreer je in de `boot()`-methode van de service provider. Door te controleren met `runningInConsole()` voorkom je onnodig laden bij webrequests.

```php theme={null}
<?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');
        }
    }
}
```

Als je `extra.laravel` instelt in de `composer.json` van je pakket, hoeven gebruikers de service provider niet handmatig te registreren.

```json theme={null}
"extra": {
    "laravel": {
        "providers": [
            "Vendor\\Package\\PackageServiceProvider"
        ]
    }
}
```

## Toepassingen

Enkele use cases waarin `GeneratorCommand` goed van pas komt.

<AccordionGroup>
  <Accordion title="Uitgebreide form requests">
    Een commando dat Requests genereert die extenden van een eigen basisklasse met authenticatiechecks of aangepaste validatielogica. Laat `getDefaultNamespace()` `App\Http\Requests` teruggeven.
  </Accordion>

  <Accordion title="DTO-generator">
    Een commando dat de boilerplate voor Data Transfer Objects genereert. Voorzie een stub met readonly properties en een `from()`-factorymethode.
  </Accordion>

  <Accordion title="Action-klassen">
    Een commando dat Action-klassen met één verantwoordelijkheid genereert. Genereert klassen met een `execute()`-methode in de namespace `App\Actions`.
  </Accordion>

  <Accordion title="Livewire gebruikt hetzelfde mechanisme">
    Het commando `make:livewire` is geïmplementeerd in de klasse `MakeCommand`, die `GeneratorCommand` extendt. Om tegelijk twee bestanden te genereren — een componentklasse en een Blade-view — wordt `handle()` overschreven.
  </Accordion>
</AccordionGroup>

## Testen

Met Orchestra Testbench test je dat het commando de bestanden correct genereert.

```php theme={null}
<?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();
    }
}
```

<Warning>
  Generatorcommando's schrijven naar het echte bestandssysteem. Ruim altijd op in `tearDown()`. Die wordt ook betrouwbaar uitgevoerd als een test halverwege faalt.
</Warning>

## Gerelateerde pagina's

<Columns cols={2}>
  <Card title="Laravel-pakketontwikkeling" icon="package" href="/nl/advanced/package-development">
    Bekijk de basis van pakketontwikkeling met service providers.
  </Card>

  <Card title="Laravel-pakketten testen met Orchestra Testbench" icon="flask-conical" href="/nl/advanced/package-testing">
    Bekijk hoe je een basis opzet voor het testen van pakketten.
  </Card>
</Columns>

<Info>
  Source: [Illuminate\Console\GeneratorCommand](https://github.com/laravel/framework/blob/master/src/Illuminate/Console/GeneratorCommand.php), [Illuminate\Foundation\Console\RequestMakeCommand](https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/Console/RequestMakeCommand.php)
</Info>


## Related topics

- [Feed Generator](/nl/packages/laravel-bluesky/feed-generator.md)
- [Mappenstructuur](/nl/directory-structure.md)
- [Laravel Doctor — een diagnosetool voor applicaties](/nl/blog/laravel-doctor-introduction.md)
- [进阶主题](/zh-CN/advanced/index.md)
- [Een custom authenticatieguard implementeren](/nl/advanced/custom-auth-guard.md)
