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

# Tutorial - Laravel Console Starter

> Stappenplan voor het bouwen van een consoleapp met Laravel Console Starter. Je leert commands maken, schedulen met GitHub Actions, notificaties versturen en praktische appvoorbeelden.

## Inleiding

In deze tutorial bouw je met `revolution/laravel-console-starter` een Laravel-applicatie met custom artisan-commands.

De voordelen van deze starter kit:

* **Snelle setup** — Je begint direct met het ontwikkelen van consoleapps, zonder complexe configuratie
* **Laravel-ecosysteem** — Je gebruikt de rijke functionaliteit van Laravel, zoals taskscheduling, databases en notificaties
* **Artisan-commands** — Met het krachtige Artisan-systeem van Laravel maak en beheer je eenvoudig eigen commands
* **Testbaarheid** — Je schrijft tests voor je commands met het testframework van Laravel

## Vereisten

Installeer de volgende software.

* PHP `^8.3`
* Composer ([https://getcomposer.org/](https://getcomposer.org/))
* Laravel Installer (`composer global require laravel/installer`)

## Het project opzetten

<Steps>
  <Step title="Een nieuw project maken">
    Voer in je terminal het volgende command uit.

    ```bash theme={null}
    laravel new my-app --using=revolution/laravel-console-starter --no-interaction
    ```

    De directory `my-app` wordt aangemaakt en de basisstructuur van de consoleapp wordt opgezet.

    Tijdens de installatie wordt het volgende automatisch uitgevoerd.

    * Het genereren van een `.env`-bestand op basis van `.env.example`
    * Het instellen van de applicatiesleutel met `php artisan key:generate`

    De belangrijkste directorystructuur:

    ```
    my-app/
    ├── app/Console/Commands/   # Hier plaats je custom commands
    ├── .github/workflows/
    │   └── cron.yml            # Voorbeeld van een GitHub Actions-schema
    ├── config/                 # Applicatieconfiguratie
    └── routes/console.php      # Commandregistratie
    ```
  </Step>

  <Step title="De omgevingsconfiguratie controleren">
    Standaard is e-mailverzending ingesteld op loggen (`MAIL_MAILER=log`).

    Wil je echt e-mails versturen, configureer dan in het `.env`-bestand een service zoals Mailgun, Postmark of SES.
  </Step>
</Steps>

## Een consolecommand maken

<Steps>
  <Step title="Het command genereren">
    Maak een nieuw command met het Artisan-command `make:command`.

    ```bash theme={null}
    php artisan make:command YourCommandName --command=your:command
    ```

    * `YourCommandName` — De klassenaam van het te maken command (bijvoorbeeld `SendDailyReport`)
    * `your:command` — De aanroepnaam van het command (bijvoorbeeld `report:send-daily`)

    `app/Console/Commands/YourCommandName.php` wordt gegenereerd.
  </Step>

  <Step title="Het command implementeren">
    Bewerk het gegenereerde bestand en implementeer je logica. Hieronder een voorbeeld van een Hello World-command.

    ```php theme={null}
    <?php

    namespace App\Console\Commands;

    use Illuminate\Console\Command;
    use Illuminate\Support\Facades\Log;

    class HelloWorldCommand extends Command
    {
        protected $signature = 'hello:world';
        protected $description = 'Displays a hello world message in the log';

        public function handle(): int
        {
            Log::info('Hello, World from Artisan Command!');
            $this->info('Hello, World message has been logged.');
            return Command::SUCCESS;
        }
    }
    ```

    Met `$signature` definieer je de aanroepnaam van het command en in de `handle()`-method schrijf je de logica.
  </Step>

  <Step title="Het command uitvoeren">
    ```bash theme={null}
    php artisan hello:world
    ```

    Na het uitvoeren verschijnt het bericht in `storage/logs/laravel.log` en in de console.
  </Step>
</Steps>

## Taskscheduling met GitHub Actions

Met GitHub Actions voer je commands periodiek uit zonder cronjobs op een server.

<Steps>
  <Step title="Het workflowbestand bekijken">
    De starter kit bevat een vooraf geconfigureerd `.github/workflows/cron.yml`.

    ```yaml theme={null}
    name: cron

    on:
      schedule:
        - cron: '0 0 * * *'  # Dagelijks om 0:00 UTC

    jobs:
      cron:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v6
          - uses: shivammathur/setup-php@v2
            with:
              php-version: 8.5
              coverage: none
          - run: composer install --no-dev -q
          - run: cp .env.example .env
          - run: php artisan key:generate
          - run: php artisan inspire
    ```
  </Step>

  <Step title="Het command aanpassen">
    Vervang `php artisan inspire` door je eigen command.

    ```yaml theme={null}
    - name: Run Command
      run: php artisan your:command
    ```

    Meerdere commands uitvoeren:

    ```yaml theme={null}
    - name: Run Commands
      run: |
        php artisan first:command
        php artisan second:command
    ```
  </Step>

  <Step title="Het schema aanpassen">
    Wijzig de `cron`-expressie om de uitvoeringsfrequentie in te stellen.

    | cron-expressie | Uitvoeringsmoment     |
    | -------------- | --------------------- |
    | `0 0 * * *`    | Dagelijks om 0:00 UTC |
    | `0 */6 * * *`  | Elke 6 uur            |
    | `0 0 * * 1`    | Elke maandag om 0:00  |
  </Step>

  <Step title="Gevoelige gegevens beheren met secrets">
    Voor gevoelige gegevens zoals API-sleutels en wachtwoorden gebruik je GitHub-repositorysecrets.

    Voeg secrets toe via **Settings > Secrets and variables > Actions** in je GitHub-repository en verwijs ernaar in de workflow.

    ```yaml theme={null}
    - name: Run Command with Secrets
      run: php artisan your:command
      env:
        API_KEY: ${{ secrets.API_KEY }}
        DB_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
    ```
  </Step>
</Steps>

## Notificaties

Je kunt de resultaten of fouten van commands melden via e-mail, Slack en meer.

<Steps>
  <Step title="Een notificatieklasse maken">
    ```bash theme={null}
    php artisan make:notification TaskCompleted
    ```

    `app/Notifications/TaskCompleted.php` wordt gegenereerd.
  </Step>

  <Step title="Notificatiekanalen configureren">
    Publiceer indien nodig de configuratiebestanden.

    ```bash theme={null}
    php artisan config:publish mail
    php artisan config:publish services
    ```
  </Step>

  <Step title="Een notificatie versturen vanuit een command">
    ```php theme={null}
    <?php

    namespace App\Console\Commands;

    use App\Notifications\TaskCompleted;
    use Illuminate\Console\Command;
    use Illuminate\Support\Facades\Notification;

    class ProcessDataCommand extends Command
    {
        protected $signature = 'data:process';
        protected $description = 'Data verwerken en na afronding een notificatie versturen';

        public function handle()
        {
            $this->info('Data wordt verwerkt...');

            // Verwerkingslogica...

            Notification::route('mail', 'admin@example.com')
                ->notify(new TaskCompleted('Dataverwerking succesvol afgerond'));

            return Command::SUCCESS;
        }
    }
    ```
  </Step>
</Steps>

<Info>
  Zie de [Laravel-notificatiedocumentatie](https://laravel.com/docs/notifications) voor details.
</Info>

## Praktische applicatievoorbeelden

### Voorbeeld 1: uptime-monitoring van websites met Slack-alerts

Een command dat controleert of websites online zijn en bij een gedetecteerd probleem een alert naar Slack stuurt.

<Steps>
  <Step title="Het Slack-notificatiekanaal installeren">
    ```bash theme={null}
    composer require laravel/slack-notification-channel
    ```
  </Step>

  <Step title="Het command en de notificatie maken">
    ```bash theme={null}
    php artisan make:command MonitorWebsites --command=monitor:websites
    php artisan make:notification WebsiteDown
    ```
  </Step>

  <Step title="Slack configureren">
    ```bash theme={null}
    php artisan config:publish services
    ```

    Voeg de Slack-webhook-URL toe aan `.env`.

    ```
    SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
    ```

    Werk `config/services.php` bij.

    ```php theme={null}
    'slack' => [
        'webhook_url' => env('SLACK_WEBHOOK_URL'),
    ],
    ```
  </Step>

  <Step title="De notificatie implementeren">
    Bewerk `app/Notifications/WebsiteDown.php`.

    ```php theme={null}
    <?php

    namespace App\Notifications;

    use Illuminate\Notifications\Messages\SlackMessage;
    use Illuminate\Notifications\Notification;

    class WebsiteDown extends Notification
    {
        public function __construct(
            protected string $website,
            protected string $error,
        ) {}

        public function via($notifiable): array
        {
            return ['slack'];
        }

        public function toSlack($notifiable): SlackMessage
        {
            return (new SlackMessage)
                ->error()
                ->content('Website-down-alert!')
                ->attachment(function ($attachment) {
                    $attachment->title($this->website)
                               ->content("Fout: {$this->error}")
                               ->timestamp(now());
                });
        }
    }
    ```
  </Step>

  <Step title="Het command implementeren">
    Bewerk `app/Console/Commands/MonitorWebsites.php`.

    ```php theme={null}
    <?php

    namespace App\Console\Commands;

    use App\Notifications\WebsiteDown;
    use Illuminate\Console\Command;
    use Illuminate\Support\Facades\Http;
    use Illuminate\Support\Facades\Log;
    use Illuminate\Support\Facades\Notification;

    class MonitorWebsites extends Command
    {
        protected $signature = 'monitor:websites {--timeout=10}';
        protected $description = 'Controleert of websites bereikbaar zijn en stuurt bij downtime een Slack-alert';

        protected array $websites = [
            'https://example.com',
            'https://yourwebsite.com',
        ];

        public function handle(): int
        {
            $timeout = (int) $this->option('timeout');
            $webhookUrl = config('services.slack.webhook_url');
            $hasErrors = false;

            foreach ($this->websites as $website) {
                try {
                    $response = Http::timeout($timeout)->get($website);
                    if ($response->successful()) {
                        $this->info("{$website}: online ✓");
                    } else {
                        $error = "HTTP-status: " . $response->status();
                        $this->error("{$website}: down ({$error})");
                        Notification::route('slack', $webhookUrl)
                            ->notify(new WebsiteDown($website, $error));
                        $hasErrors = true;
                    }
                } catch (\Exception $e) {
                    $this->error("{$website}: fout ({$e->getMessage()})");
                    Log::error("Controle van {$website} mislukt", ['error' => $e->getMessage()]);
                    Notification::route('slack', $webhookUrl)
                        ->notify(new WebsiteDown($website, $e->getMessage()));
                    $hasErrors = true;
                }
            }

            return $hasErrors ? Command::FAILURE : Command::SUCCESS;
        }
    }
    ```
  </Step>

  <Step title="Schedulen met GitHub Actions">
    Werk `.github/workflows/cron.yml` bij.

    ```yaml theme={null}
    name: Website Monitoring

    on:
      schedule:
        - cron: '*/15 * * * *'  # Elke 15 minuten uitvoeren

    jobs:
      monitor:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v6
          - uses: shivammathur/setup-php@v2
            with:
              php-version: 8.5
          - run: composer install --no-dev -q
          - run: cp .env.example .env
          - run: php artisan key:generate
          - name: Monitor Websites
            run: php artisan monitor:websites
            env:
              SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
    ```
  </Step>
</Steps>

### Voorbeeld 2: cryptoportfolio-updates met Discord-notificaties

Een command dat cryptovalutaprijzen ophaalt via de CoinGecko-API en updates verstuurt via een Discord-webhook.

<Steps>
  <Step title="Het Discord-notificatiekanaal installeren">
    ```bash theme={null}
    composer require revolution/laravel-notification-discord-webhook
    ```
  </Step>

  <Step title="Het command en de notificatie maken">
    ```bash theme={null}
    php artisan make:command UpdateCryptoPortfolio --command=crypto:portfolio
    php artisan make:notification CryptoPortfolioUpdate
    ```
  </Step>

  <Step title="Discord configureren">
    Voeg de Discord-webhook-URL toe aan `.env`.

    ```
    DISCORD_WEBHOOK=https://discord.com/api/webhooks/YOUR/WEBHOOK
    ```

    Werk `config/services.php` bij.

    ```php theme={null}
    'discord' => [
        'webhook' => env('DISCORD_WEBHOOK'),
    ],
    ```
  </Step>

  <Step title="Het command implementeren en uitvoeren">
    Zie de [tutorial in de GitHub-repository](https://github.com/invokable/laravel-console-starter/blob/main/docs/tutorial_ja.md) voor de gedetailleerde implementatie.

    ```bash theme={null}
    php artisan crypto:portfolio
    ```
  </Step>
</Steps>

### Voorbeeld 3: websitecontent scrapen met e-mailnotificaties

Een command dat content van een website scrapet en het resultaat per e-mail verstuurt.

<Steps>
  <Step title="Het command en de notificatie maken">
    ```bash theme={null}
    php artisan make:command WebScraper --command=scrape:website
    php artisan make:notification ScrapingCompleted
    ```
  </Step>

  <Step title="E-mail configureren">
    ```bash theme={null}
    php artisan config:publish mail
    ```

    Voeg de e-mailconfiguratie toe aan het `.env`-bestand.

    ```
    MAIL_MAILER=smtp
    MAIL_HOST=smtp.mailtrap.io
    MAIL_PORT=2525
    MAIL_USERNAME=your_username
    MAIL_PASSWORD=your_password
    MAIL_ENCRYPTION=tls
    MAIL_FROM_ADDRESS=your-app@example.com
    MAIL_FROM_NAME="${APP_NAME}"
    ```
  </Step>

  <Step title="Het command implementeren en uitvoeren">
    ```php theme={null}
    protected $signature = 'scrape:website {--url=https://example.com} {--email=admin@example.com}';

    public function handle(): int
    {
        $url = $this->option('url');
        $email = $this->option('email');

        $response = Http::timeout(30)->get($url);

        // De content verwerken en de notificatie versturen...
        Notification::route('mail', $email)
            ->notify(new ScrapingCompleted(true, $url, $title, $content));

        return Command::SUCCESS;
    }
    ```

    ```bash theme={null}
    php artisan scrape:website --email=admin@example.com
    ```
  </Step>
</Steps>

## Volgende stappen

Je hebt nu de basis geleerd van Laravel-consoleapplicaties met `revolution/laravel-console-starter`.

Om je verder te verdiepen:

* **Verken de Laravel-documentatie** — Bekijk in de [officiële Laravel-documentatie](https://laravel.com/docs) welke functies je consoleapp kunnen versterken
* **Implementeer tests** — Schrijf tests voor je commands met het testframework van Laravel en waarborg de betrouwbaarheid
* **Overweeg pakketontwikkeling** — Maak je vergelijkbare commands in meerdere projecten, overweeg dan om ze te publiceren als herbruikbaar Laravel-pakket
* **Blijf op de hoogte** — Volg [Laravel News](https://laravel-news.com/) en de officiële blog om best practices bij te houden


## Related topics

- [Laravel Console Starter](/nl/packages/laravel-console-starter/index.md)
- [Starter kits](/nl/starter-kits.md)
- [Een Laravel starter kit maken](/nl/advanced/starter-kit-creation.md)
- [Introductie tot authenticatie](/nl/authentication.md)
- [Consoletests](/nl/console-tests.md)
