Weave 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

The Console component eases the creation of beautiful and testable command line interfaces for PHP applications, with support for input/output handling, styling, and argument parsing.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal setup for a Laravel app

  1. Check the installed version first:

    composer show symfony/console
    

    Laravel already depends on symfony/console through Artisan; you normally should not run composer require symfony/console in a Laravel application unless you are building a standalone console app. If your app is locked to the Symfony Console 5.4 LTS line, update to at least v5.4.54 because of the security patch that escapes context strings written to the terminal (#65692). For newer Symfony branches, use the corresponding patched release.

  2. Create a command:

    php artisan make:command GreetCommand
    
    <?php
    
    namespace App\Console\Commands;
    
    use Illuminate\Console\Command;
    
    class GreetCommand extends Command
    {
        protected $signature = 'test:greet {name?}';
        protected $description = 'Display a greeting';
    
        public function handle(): int
        {
            $name = $this->argument('name') ?: 'World';
    
            $this->info("Hello, {$name}!");
    
            return self::SUCCESS;
        }
    }
    
  3. Registration:

    • Laravel 11+ auto-discovers commands in app/Console/Commands.
    • Older Laravel versions register commands in app/Console/Kernel.php via $commands, or rely on the framework’s command discovery depending on version.
  4. Run it:

    php artisan test:greet Laravel
    

Where to look first

  • Laravel Artisan documentation for command signatures, input/output helpers, and testing.
  • Symfony Console documentation for lower-level behavior: Command, Application, InputInterface, OutputInterface, SymfonyStyle.
  • Core classes:
    • Illuminate\Console\Command
    • Symfony\Component\Console\Input\InputInterface
    • Symfony\Component\Console\Output\OutputInterface
    • Symfony\Component\Console\Style\SymfonyStyle

First useful use case

Start with a small operational command: accept one or two arguments/options, perform a service-layer action, print a clear result, and return a meaningful exit code. This keeps commands thin and testable.


Implementation Patterns

1. Command signature and input

Define arguments and options in $signature, then read them in handle():

protected $signature = 'user:create
    {name : The user name}
    {email : The user email}
    {--admin : Create as administrator}';

public function handle(): int
{
    $name = $this->argument('name');
    $email = $this->argument('email');
    $isAdmin = (bool) $this->option('admin');

    // Delegate to a service/action class...

    return self::SUCCESS;
}

Use $this->argument() and $this->option() rather than reading $_SERVER['argv'] directly.

2. Validation and prompts

Laravel commands do not have a built-in validateArguments() hook. Validate inside handle() or delegate to Laravel’s validator/service layer:

$validator = validator(
    ['email' => $this->argument('email')],
    ['email' => ['required', 'email']]
);

if ($validator->fails()) {
    foreach ($validator->errors()->all() as $error) {
        $this->error($error);
    }

    return self::FAILURE;
}

Interactive helpers:

if (! $this->confirm('Proceed?', false)) {
    return self::SUCCESS;
}

$name = $this->ask('Your name');
$password = $this->secret('Password');
$environment = $this->choice('Environment', ['dev', 'staging', 'prod'], 'dev');

Guard interactive prompts when commands may run in CI or queued/scheduled contexts:

if (! $this->input->isInteractive()) {
    // Use defaults or fail fast.
}

3. Output and formatting

Prefer Laravel’s output helpers so tests can assert output:

$this->info('Success!');
$this->error('Failed!');
$this->warn('Warning');
$this->line('Plain text');
$this->comment('Hint');

Tables:

$this->table(
    ['Name', 'Email'],
    [
        ['Laravel', '[email protected]'],
    ]
);

Progress bars:

$bar = $this->output->createProgressBar($total);

foreach ($items as $item) {
    // Process item...
    $bar->advance();
}

$bar->finish();
$this->newLine(2);

Illuminate\Console\OutputStyle extends Symfony’s SymfonyStyle, so richer section/title helpers are also available through $this->output when needed.

4. Calling other commands

Inside a command:

$this->call('cache:clear');

Programmatically:

use Illuminate\Support\Facades\Artisan;

Artisan::call('cache:clear');
$output = Artisan::output();

Keep cross-command orchestration shallow; prefer service classes for shared logic.

5. Testing commands

Laravel’s Artisan test helpers are usually the best fit:

public function test_greet_command(): void
{
    $this->artisan('test:greet', ['name' => 'Laravel'])
        ->expectsOutput('Hello, Laravel!')
        ->assertExitCode(0);
}

For interactive commands:

$this->artisan('user:create')
    ->expectsQuestion('Your name', 'Taylor')
    ->expectsQuestion('Password', 'secret')
    ->assertExitCode(0);

Symfony\Component\Console\Tester\CommandTester is useful for standalone Symfony Console commands, but Laravel command tests are usually simpler with $this->artisan().

6. Events and signals

Symfony Console emits console events such as ConsoleEvents::COMMAND, TERMINATE, and ERROR. In Laravel, register listeners in a service provider:

use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Illuminate\Support\Facades\Event;

Event::listen(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
    // Inspect or adjust the command/input/output.
});

For graceful shutdown behavior, implement Symfony’s SignalableCommandInterface instead of inventing a custom signal hook.


Gotchas and Tips

Security: escape untrusted terminal output

The v5.4.54 security release escapes context strings written to the terminal (#65692). This matters when user-controlled data, exception messages, or external input can contain terminal escape sequences.

  • Update Symfony Console to a patched version. On the 5.4 LTS line, use >=5.4.54.
  • Avoid raw echo or unescaped writeln() with untrusted strings.
  • Escape user-supplied text before printing it through Symfony’s formatter:
use Symfony\Component\Console\Formatter\OutputFormatter;

$this->line(OutputFormatter::escape($userInput));
  • Do not assume styled output is safe just because it is rendered by Artisan. Formatting tags and terminal control sequences need care.

Laravel version differences

  • Laravel 11+ no longer has app/Console/Kernel.php; commands in app/Console/Commands are auto-discovered.
  • Older Laravel applications may still use app/Console/Kernel.php and $commands.
  • Do not manually add symfony/console to a Laravel app unless you have a specific standalone-console need. Let Laravel’s dependency constraints manage it.

Output mixing and testability

Avoid mixing direct echo/print with Artisan output. Direct writes bypass OutputInterface, break output styling, and make expectsOutput() assertions unreliable. Use $this->line(), $this->info(), $this->output->write(), etc.

Interactive commands in CI

Prompts can hang or fail in non-interactive environments. Check $this->input->isInteractive(), provide sensible defaults, and run CI commands with --no-interaction where appropriate.

Exit codes matter

Return an integer exit code instead of void:

return self::SUCCESS;
return self::FAILURE;

This makes commands friendlier to schedulers, shell scripts, and tests.

Progress bars and sections

Finish progress bars and add a newline before printing more output. Mixing progress bars with sections or arbitrary writes can produce messy output. Use $bar->clear() before important messages if needed.

Debugging

Use verbosity flags:

php artisan test:greet Laravel -v
php artisan test:greet Laravel -vvv

Inside code:

$this->output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);

Useful checks:

  • php artisan list to inspect registered commands.
  • php artisan help test:greet to inspect signature/options.
  • Artisan::output() after Artisan::call() in tests or debugging code.
  • Hidden commands can still be invoked directly if you know the command name.

Extension points

  • Inject services through the container into handle() or the command constructor.
  • Extract business logic into action/service classes; commands should mainly parse input, call services, and render output.
  • Use Symfony Console events for cross-cutting console behavior.
  • Implement SignalableCommandInterface for signal-aware commands.
  • For standalone Symfony Console applications, use Application, CommandTester, and HelperSet directly; inside Laravel, prefer Artisan’s command and testing helpers.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource