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

Symfony Command Laravel Package

drjele/symfony-command

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require drjele/symfony-command
    

    Add the package to your composer.json under require or require-dev depending on your use case.

  2. Basic Usage Create a new command by extending DrJele\Command\Command (or DrJele\Command\ConsoleCommand for Symfony Console integration):

    use DrJele\Command\Command;
    
    class MyCommand extends Command
    {
        protected function configure(): void
        {
            $this->setName('app:my-command')
                 ->setDescription('A simple command example');
        }
    
        protected function execute(InputInterface $input, OutputInterface $output): int
        {
            $output->writeln('Hello from MyCommand!');
            return Command::SUCCESS;
        }
    }
    
  3. Registering the Command For Symfony, register the command in config/services.yaml:

    services:
        App\Command\MyCommand:
            tags: ['console.command']
    

    For Laravel, bind the command in a service provider:

    $this->app->bind(Command::class, function ($app) {
        return new MyCommand();
    });
    
  4. First Use Case Run the command via CLI:

    php bin/console app:my-command
    

Implementation Patterns

Core Workflows

  1. Command Lifecycle

    • configure(): Define command metadata (name, description, arguments, options).
    • execute(): Core logic. Use $input for arguments/options, $output for I/O.
    • initialize(): Pre-execution setup (e.g., dependency injection).
    • interact(): For interactive prompts (e.g., confirmation dialogs).
  2. Argument/Option Handling Use Symfony’s Argument and Option classes for validation:

    protected function configure(): void
    {
        $this->addArgument('name', InputArgument::REQUIRED, 'Your name')
             ->addOption('verbose', 'v', InputOption::VALUE_NONE, 'Enable verbose mode');
    }
    
  3. Dependency Injection Inject services via constructor or initialize():

    private $logger;
    
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    
  4. Output Formatting Leverage $output methods:

    $output->writeln('<info>Info message</info>');
    $output->section('Section Title');
    $output->table(['Header'], [['Data']]);
    
  5. Subcommands Group related commands under a parent:

    // Parent command
    $this->addCommand(new SubCommand1());
    $this->addCommand(new SubCommand2());
    
  6. Event Listeners Attach listeners to command events (e.g., CommandEvent::START, CommandEvent::END):

    $this->getDispatcher()->addListener(CommandEvent::START, function (CommandEvent $event) {
        // Pre-execution logic
    });
    
  7. Progress Bars Use Symfony’s ProgressBar for long-running tasks:

    $progress = new ProgressBar($output, 100);
    for ($i = 0; $i < 100; $i++) {
        $progress->advance();
    }
    

Integration Tips

  1. Laravel Integration

    • Use Artisan::call() to trigger commands programmatically:
      $exitCode = Artisan::call('app:my-command', ['name' => 'John']);
      
    • Extend Illuminate\Console\Command and merge with DrJele\Command\Command for hybrid usage.
  2. Symfony Integration

    • Prefer DrJele\Command\ConsoleCommand for Symfony’s Command base class.
    • Use Symfony’s ContainerAwareCommand for DI containers.
  3. Testing Commands Mock InputInterface and OutputInterface:

    $input = $this->createMock(InputInterface::class);
    $output = $this->createMock(OutputInterface::class);
    $command = new MyCommand();
    $command->run($input, $output);
    
  4. Reusable Command Logic Extract shared logic into traits or base classes:

    trait HandlesUsers
    {
        public function getUser(string $id): User
        {
            // Shared logic
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Output Buffering

    • Symfony’s OutputInterface buffers output by default. Use $output->flush() to force immediate display:
      $output->writeln('Processing...');
      $output->flush();
      
  2. Argument/Option Validation

    • Always validate inputs in execute() to avoid silent failures:
      if (!$input->getArgument('name')) {
          throw new \RuntimeException('Name is required.');
      }
      
  3. Dependency Injection in execute()

    • Avoid instantiating services directly in execute(). Use constructor injection or initialize().
  4. Command Naming Conflicts

    • Ensure command names are unique across your application to avoid CLI ambiguity.
  5. Symfony vs. Laravel Quirks

    • Symfony: Commands are autoloaded via tags: ['console.command'].
    • Laravel: Commands must be registered in a service provider or app/Console/Kernel.php.
  6. Progress Bar Interruption

    • Progress bars may not update correctly if the command exits early. Use try-catch blocks to handle interruptions:
      try {
          $progress->finish();
      } catch (\Exception $e) {
          $progress->setMessage('Failed: ' . $e->getMessage());
      }
      

Debugging

  1. Verbose Output Enable verbose mode to debug:

    php bin/console app:my-command -vvv
    
  2. Logging Use Symfony’s LoggerInterface for structured logs:

    $this->logger->debug('Debug message', ['context' => 'key' => 'value']);
    
  3. Command Events Debug event listeners by dumping the event object:

    $this->getDispatcher()->addListener(CommandEvent::START, function (CommandEvent $event) {
        var_dump($event->getCommand()->getName());
    });
    

Extension Points

  1. Custom Command Events Dispatch custom events for extensibility:

    $this->getDispatcher()->dispatch(new MyCustomEvent($input, $output));
    
  2. Command Helpers Create helper classes for shared functionality (e.g., CommandHelper::validateEmail()).

  3. Interactive Prompts Use Symfony’s QuestionHelper for advanced interactions:

    $helper = $this->getHelper('question');
    $question = new ConfirmationQuestion('Continue? [y/N] ', false);
    if (!$helper->ask($input, $output, $question)) {
        return Command::FAILURE;
    }
    
  4. Command Metadata Extend metadata with custom attributes:

    $this->setDescription('Command with custom metadata')
         ->setAttribute('category', 'utils');
    
  5. Command Groups Organize commands into logical groups for better CLI navigation:

    php bin/console list app
    
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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log