Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Console Laravel Package

symfony/console

Symfony Console component for building beautiful, testable CLI apps in PHP. Define commands and arguments, render styled output, handle prompts and hidden input, and integrate easily into frameworks or standalone scripts with strong tooling and docs.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require symfony/console:^8.1
    

    Laravel 10+ includes Symfony Console 8.1+ by default. For compatibility, ensure your composer.json aligns with Laravel’s dependencies.

  2. First Command:

    php artisan make:command SendEmail
    

    This generates a scaffold with:

    • handle(): Core logic execution.
    • configure(): Defines CLI signature (arguments/options).
  3. Run It:

    php artisan send:email
    
  4. Key Files to Explore:

    • app/Console/Kernel.php: Command registration.
    • vendor/symfony/console/: Core classes (Command, Input, Output).
    • Laravel’s artisan CLI (extends symfony/console/Application).
    • New in v8.1.0-BETA3: Focus on symfony/polyfill-php85 for PHP 8.5+ fixes and hardened error handling (see #64246).

First Use Case: User-Facing CLI Tool

Replace a Bash script with a Laravel command to send emails:

// app/Console/Commands/SendEmail.php
protected $signature = 'send:email {recipient} {--subject=Hello} {--body=Default body}';
protected $description = 'Send an email to a user';

public function handle()
{
    $this->info("Sending email to {$this->argument('recipient')}...");
    // Logic here (e.g., Mail::send())
    $this->success('Email sent!');
}

Run with:

php artisan send:email user@example.com --subject="Welcome" --body="Thanks!"

Implementation Patterns

1. Command Structure

  • Signature: Define arguments/options in configure():
    $this->argument('id', 'The user ID')
         ->option('force', 'Bypass confirmation', 'f');
    
  • Validation: Use Symfony’s Validator or custom logic:
    if (!$this->option('force') && !$this->confirm('Proceed?')) {
        return;
    }
    

2. Output Handling

  • Styled Output: Use Output methods:
    $this->text('Normal text');
    $this->line('<info>Colored text</info>');
    $this->table(['Headers'], $data);
    
  • Verbosity Levels: Leverage VERBOSITY_* constants:
    if ($this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) {
        $this->debug('Debug info');
    }
    

3. Interactive Prompts

  • Ask for Input:
    $name = $this->ask('Your name?');
    $confirm = $this->confirm('Continue?', false);
    $choice = $this->choice('Pick one', ['A', 'B'], 'A');
    
  • Hidden Input:
    $password = $this->secret('Password?');
    

4. Progress Tracking

  • Progress Bar:
    $progress = $this->output->createProgressBar($total);
    for ($i = 0; $i < $total; $i++) {
        $progress->advance();
    }
    $progress->finish();
    
  • Indeterminate Progress:
    $indicator = $this->output->createProgressIndicator('Processing...');
    $indicator->start();
    sleep(2);
    $indicator->finish();
    
    Fix in v8.1.0-BETA3: Hardened ProgressIndicator to prevent race conditions during concurrent output (see #64246).

5. Integration with Laravel

  • Access Services:
    $user = $this->container->get('App\Models\User')->find($id);
    
  • Events/Listeners: Trigger events in handle():
    event(new EmailSent($user));
    

6. Testing Commands

  • Unit Test:
    $command = new SendEmail();
    $command->setLaravel($app);
    $command->handle();
    
  • Integration Test:
    $this->artisan('send:email', ['recipient' => 'test@example.com'])
         ->expectsQuestion('Proceed?', 'yes')
         ->assertExitCode(0);
    

7. Advanced Patterns

  • Subcommands: Group related commands (e.g., php artisan user:create).
  • Command Bus: Dispatch commands to services:
    $this->dispatch(new SendEmailJob($email));
    
  • Custom Helpers: Extend SymfonyStyle for reusable UI:
    $style = new SymfonyStyle($this->input, $this->output);
    $style->title('My Tool');
    

Gotchas and Tips

Pitfalls

  1. Argument Parsing Quirks:

    • Hidden Commands: Use -- to bypass argument parsing:
      php artisan --hidden command:name
      
    • Option Conflicts: Avoid overlapping short/long options (e.g., -f vs --force).
  2. Output Corruption:

    • Windows Line Endings: Use \n consistently.
    • Binary Data: Use OUTPUT_RAW mode:
      $this->output->write($binaryData, false, OutputInterface::OUTPUT_RAW);
      
    • Fix in v8.1.0-BETA3: ConsoleSectionOutput now handles concurrent writes more robustly (see #64246).
  3. Signal Handling:

    • Termination: Handle SIGINT (Ctrl+C) gracefully:
      $this->output->getErrorOutput()->write("\nExiting...\n");
      exit(0);
      
  4. Testing Gotchas:

    • Verbosity: Override explicitly in tests:
      $tester->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
      
    • Interactive Mode: Mock prompts:
      $this->artisan('command')->expectsQuestion('?', 'answer');
      
  5. Performance:

    • Progress Bars: Batch advance() calls in loops.
    • Output Buffers: Disable buffering for real-time output:
      $this->output->setDecorated(false);
      

Debugging Tips

  1. Enable Debug Mode:
    php artisan --env=local --verbose command
    
  2. Log Input/Output:
    $this->output->writeln(sprintf('<comment>Input:</comment> %s', print_r($this->input->getArguments(), true)));
    
  3. Check for Deprecations:
    • Symfony Console deprecates getApplication() in favor of dependency injection.
    • New in v8.1.0-BETA3: Hardened error handling for edge cases (e.g., malformed input).

Extension Points

  1. Custom Output Formatters:
    • Extend OutputFormatter for JSON/CSV output:
      $formatter = new JsonOutputFormatter();
      $this->output->setFormatter($formatter);
      
  2. Command Helpers:
    • Create a base command class:
      abstract class BaseCommand extends Command {
          protected function log($message) { /* ... */ }
      }
      
  3. Shell Integration:
    • Use Shell for cross-platform commands:
      $shell = new Shell();
      $shell->execute('ls -la');
      

Laravel-Specific Tips

  1. Artisan Commands:
    • Override Artisan for global options in app/Console/Kernel.php:
      protected $commands = [Commands\SendEmail::class];
      
  2. Service Container:
    • Bind commands for DI:
      $this->app->bind('command.send.email', function () {
          return new SendEmail($mailer);
      });
      
  3. Scheduling:
    • Use schedule() in handle() for delayed execution:
      $this->dispatch(new SendEmailJob($email));
      
  4. New in v8.1.0-BETA3:
    • PHP 8.5 Compatibility: Ensure symfony/polyfill-php85 is installed.
    • Hardened CLI: Improved handling of edge cases (e.g., concurrent output, malformed input).

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai