> ## 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

> Pasos para construir una aplicación de consola con Laravel Console Starter. Aprende a crear comandos, programarlos con GitHub Actions, enviar notificaciones y ver ejemplos prácticos.

## Introducción

En este tutorial construirás una aplicación Laravel con comandos artisan personalizados usando `revolution/laravel-console-starter`.

Ventajas de usar este starter kit:

* **Configuración rápida**: puedes empezar a desarrollar aplicaciones de consola de inmediato, sin configuraciones complejas.
* **Ecosistema Laravel**: puedes utilizar la programación de tareas, la base de datos, las notificaciones y todas las funcionalidades de Laravel.
* **Comandos Artisan**: crea y gestiona fácilmente comandos personalizados con el potente sistema Artisan de Laravel.
* **Facilidad para testear**: puedes escribir tests para tus comandos con el framework de testing de Laravel.

## Requisitos previos

Instala el siguiente software.

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

## Configuración del proyecto

<Steps>
  <Step title="Crea un nuevo proyecto">
    Ejecuta en la terminal el siguiente comando.

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

    Se crea el directorio `my-app` con la estructura básica de una aplicación de consola.

    Durante la instalación se ejecutan automáticamente:

    * Generación del archivo `.env` a partir de `.env.example`
    * Configuración de la clave de la aplicación con `php artisan key:generate`

    Estructura principal de directorios:

    ```
    my-app/
    ├── app/Console/Commands/   # Ubica aquí tus comandos personalizados
    ├── .github/workflows/
    │   └── cron.yml            # Ejemplo de programación con GitHub Actions
    ├── config/                 # Configuración de la aplicación
    └── routes/console.php      # Registro de comandos
    ```
  </Step>

  <Step title="Verifica la configuración de entorno">
    Por defecto el envío de correo está configurado para escribir en el log (`MAIL_MAILER=log`).

    Si necesitas enviar correos reales, configura un servicio como Mailgun, Postmark o SES en el archivo `.env`.
  </Step>
</Steps>

## Crear comandos de consola

<Steps>
  <Step title="Genera el comando">
    Crea un nuevo comando con el comando Artisan `make:command`.

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

    * `YourCommandName`: nombre de la clase del comando (por ejemplo, `SendDailyReport`).
    * `your:command`: nombre de invocación del comando (por ejemplo, `report:send-daily`).

    Se genera `app/Console/Commands/YourCommandName.php`.
  </Step>

  <Step title="Implementa el comando">
    Edita el archivo generado e implementa la lógica. A continuación tienes un ejemplo de comando Hello World.

    ```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;
        }
    }
    ```

    En `$signature` defines el nombre de invocación y en el método `handle()` escribes la lógica.
  </Step>

  <Step title="Ejecuta el comando">
    ```bash theme={null}
    php artisan hello:world
    ```

    Tras ejecutarlo, se muestra el mensaje en `storage/logs/laravel.log` y en la consola.
  </Step>
</Steps>

## Programación de tareas con GitHub Actions

Con GitHub Actions puedes ejecutar comandos de forma periódica sin necesidad de cron en el servidor.

<Steps>
  <Step title="Revisa el archivo de workflow">
    El starter kit incluye ya configurado el archivo `.github/workflows/cron.yml`.

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

    on:
      schedule:
        - cron: '0 0 * * *'  # Todos los días a las 00: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="Cambia el comando">
    Sustituye `php artisan inspire` por tu propio comando.

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

    Para ejecutar varios comandos:

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

  <Step title="Ajusta la programación">
    Cambia la expresión `cron` para configurar la frecuencia de ejecución.

    | Expresión cron | Ejecución                      |
    | -------------- | ------------------------------ |
    | `0 0 * * *`    | Todos los días a las 00:00 UTC |
    | `0 */6 * * *`  | Cada 6 horas                   |
    | `0 0 * * 1`    | Todos los lunes a las 00:00    |
  </Step>

  <Step title="Gestiona la información sensible con secrets">
    Usa GitHub repository secrets para información sensible como claves de API o contraseñas.

    Añade los secrets en **Settings > Secrets and variables > Actions** del repositorio de GitHub y referéncialos en el 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>

## Funcionalidad de notificaciones

Puedes notificar el resultado o los errores de un comando por correo, Slack, etc.

<Steps>
  <Step title="Crea la clase de notificación">
    ```bash theme={null}
    php artisan make:notification TaskCompleted
    ```

    Se genera `app/Notifications/TaskCompleted.php`.
  </Step>

  <Step title="Configura el canal de notificación">
    Publica los archivos de configuración necesarios.

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

  <Step title="Envía la notificación desde el comando">
    ```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 = 'Procesa los datos y envía notificación al finalizar';

        public function handle()
        {
            $this->info('Procesando datos...');

            // Lógica de procesamiento...

            Notification::route('mail', 'admin@example.com')
                ->notify(new TaskCompleted('El procesamiento de datos se ha completado correctamente'));

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

<Info>
  Para más detalles, consulta la [documentación de notificaciones de Laravel](https://laravel.com/docs/notifications).
</Info>

## Ejemplos prácticos de aplicación

### Ejemplo 1: Monitorización de sitios web con alertas en Slack

Comando que comprueba si un sitio web está online y envía una alerta a Slack si se detecta un problema.

<Steps>
  <Step title="Instala el canal de notificación de Slack">
    ```bash theme={null}
    composer require laravel/slack-notification-channel
    ```
  </Step>

  <Step title="Crea el comando y la notificación">
    ```bash theme={null}
    php artisan make:command MonitorWebsites --command=monitor:websites
    php artisan make:notification WebsiteDown
    ```
  </Step>

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

    Añade la URL del webhook de Slack en `.env`.

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

    Actualiza `config/services.php`.

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

  <Step title="Implementa la notificación">
    Edita `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('¡Alerta: sitio web caído!')
                ->attachment(function ($attachment) {
                    $attachment->title($this->website)
                               ->content("Error: {$this->error}")
                               ->timestamp(now());
                });
        }
    }
    ```
  </Step>

  <Step title="Implementa el comando">
    Edita `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 = 'Comprueba la disponibilidad de sitios web y envía una alerta a Slack si están caídos';

        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}: caído ({$error})");
                        Notification::route('slack', $webhookUrl)
                            ->notify(new WebsiteDown($website, $error));
                        $hasErrors = true;
                    }
                } catch (\Exception $e) {
                    $this->error("{$website}: error ({$e->getMessage()})");
                    Log::error("Fallo al comprobar {$website}", ['error' => $e->getMessage()]);
                    Notification::route('slack', $webhookUrl)
                        ->notify(new WebsiteDown($website, $e->getMessage()));
                    $hasErrors = true;
                }
            }

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

  <Step title="Programa con GitHub Actions">
    Actualiza `.github/workflows/cron.yml`.

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

    on:
      schedule:
        - cron: '*/15 * * * *'  # Cada 15 minutos

    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>

### Ejemplo 2: Actualización de cartera de criptomonedas con notificación en Discord

Comando que obtiene los precios de criptomonedas desde la API de CoinGecko y envía la actualización mediante un webhook de Discord.

<Steps>
  <Step title="Instala el canal de notificación de Discord">
    ```bash theme={null}
    composer require revolution/laravel-notification-discord-webhook
    ```
  </Step>

  <Step title="Crea el comando y la notificación">
    ```bash theme={null}
    php artisan make:command UpdateCryptoPortfolio --command=crypto:portfolio
    php artisan make:notification CryptoPortfolioUpdate
    ```
  </Step>

  <Step title="Configura Discord">
    Añade la URL del webhook de Discord en `.env`.

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

    Actualiza `config/services.php`.

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

  <Step title="Implementa el comando y ejecútalo">
    Consulta la implementación detallada en el [tutorial del repositorio de GitHub](https://github.com/invokable/laravel-console-starter/blob/main/docs/tutorial_ja.md).

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

### Ejemplo 3: Scraping de contenido web y notificación por correo

Comando que hace scraping de contenido de un sitio web y envía el resultado por correo.

<Steps>
  <Step title="Crea el comando y la notificación">
    ```bash theme={null}
    php artisan make:command WebScraper --command=scrape:website
    php artisan make:notification ScrapingCompleted
    ```
  </Step>

  <Step title="Configura el correo">
    ```bash theme={null}
    php artisan config:publish mail
    ```

    Añade la configuración de correo en el archivo `.env`.

    ```
    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="Implementa el comando y ejecútalo">
    ```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);

        // Procesa el contenido y envía la notificación...
        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>

## Próximos pasos

Ya has aprendido los fundamentos para desarrollar aplicaciones de consola con Laravel usando `revolution/laravel-console-starter`.

Para profundizar más:

* **Explora la documentación de Laravel**: revisa las funcionalidades que pueden potenciar tu app de consola en la [documentación oficial de Laravel](https://laravel.com/docs).
* **Implementa pruebas**: crea tests para tus comandos con el framework de testing de Laravel para asegurar su fiabilidad.
* **Considera crear paquetes**: si vas a reutilizar los mismos comandos en varios proyectos, considera publicarlos como paquetes reutilizables de Laravel.
* **Mantente al día**: sigue [Laravel News](https://laravel-news.com/) y el blog oficial para conocer las buenas prácticas más recientes.


## Related topics

- [Laravel Console Starter](/es/packages/laravel-console-starter/index.md)
- [Starter kits](/es/starter-kits.md)
- [Cómo crear un starter kit de Laravel](/es/advanced/starter-kit-creation.md)
- [Instalación](/es/installation.md)
- [Tutorial de bots - Laravel Bluesky](/es/packages/laravel-bluesky/bot-tutorial.md)
