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

Base Command Bundle Laravel Package

afrihost/base-command-bundle

Symfony bundle providing an opinionated base class for console commands to reduce boilerplate. Adds built-in initialization for common needs like logging and locking, with global defaults via config and per-command or runtime overrides for flexible behavior.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require afrihost/base-command-bundle
    

    Register the bundle in config/bundles.php:

    return [
        // ...
        Afrihost\BaseCommandBundle\AfrihostBaseCommandBundle::class => ['all' => true],
    ];
    
  2. First Command Extend BaseCommand in your custom command:

    use Afrihost\BaseCommandBundle\Command\BaseCommand;
    
    namespace App\Command;
    
    class MyCommand extends BaseCommand
    {
        protected static $defaultName = 'app:my-command';
    
        protected function configure()
        {
            $this->setDescription('A minimal command using BaseCommandBundle');
        }
    
        protected function execute(InputInterface $input, OutputInterface $output): int
        {
            $this->logInfo('Command executed!'); // Built-in logging
            return Command::SUCCESS;
        }
    }
    
  3. Key Features Out-of-the-Box

    • Logging: Use $this->logInfo(), $this->logError(), etc. (inherited from BaseCommand).
    • Locking: Enable via setLockEnabled(true) in configure() or runtime.
    • Configuration: Override defaults in config/packages/afrihost_base_command.yaml:
      afrihost_base_command:
          log_to_console: true
          default_log_level: 'info'
      

Implementation Patterns

1. Command Lifecycle Hooks

Leverage built-in hooks for consistent behavior:

protected function initialize(InputInterface $input, OutputInterface $output)
{
    $this->logDebug('Initializing command...');
    parent::initialize($input, $output);
}

protected function interact(InputInterface $input, OutputInterface $output)
{
    $this->askAndValidate($input, $output, 'confirm', 'Proceed?', function ($answer) {
        return $answer === 'yes';
    });
}

2. Dynamic Configuration

Override global defaults per-command:

protected function configure()
{
    $this->setLockEnabled(true) // Force locking for this command
         ->setLogLevel('debug'); // Override log level
}

3. Locking Mechanism

Use setLockEnabled() and setLockTTL() (in seconds) to prevent concurrent executions:

protected function configure()
{
    $this->setLockEnabled(true)
         ->setLockTTL(3600); // Lock for 1 hour
}

4. Input Validation

Reuse validation helpers:

protected function execute(InputInterface $input, OutputInterface $output)
{
    $this->validateRequiredOption($input, 'option-name', 'Option is required!');
    // ...
}

5. Service Integration

Access Laravel services via Symfony’s container:

protected function execute(InputInterface $input, OutputInterface $output)
{
    $userRepository = $this->getContainer()->get('App\Repository\UserRepository');
    // ...
}

6. Bulk Operations

For commands processing multiple items (e.g., records), use processItems():

protected function execute(InputInterface $input, OutputInterface $output)
{
    $items = $this->getItemsToProcess();
    $this->processItems($items, function ($item) use ($output) {
        $this->logInfo(sprintf('Processing %s', $item->id));
        // Process logic here
    });
}

Gotchas and Tips

Pitfalls

  1. Locking Conflicts

    • If a command fails mid-execution, the lock may linger. Use setLockTTL() to auto-release locks.
    • Debug Tip: Check var/log/ for lock-related errors if commands hang.
  2. Logging Duplication

    • If log_to_console: true is set globally, logs may appear twice (console + file). Override per-command:
      $this->setLogToConsole(false);
      
  3. Container Access in Tests

    • Mock the container when testing commands:
      $command = new MyCommand();
      $command->setContainer($this->createMock(ContainerInterface::class));
      
  4. Deprecated Symfony Features

    • The bundle was last updated in 2020 and may not support newer Symfony versions (e.g., Symfony 6+). Test thoroughly.

Debugging Tips

  • Enable Verbose Logging:
    # config/packages/afrihost_base_command.yaml
    afrihost_base_command:
        default_log_level: 'debug'
    
  • Check Lock Status: Use php bin/console debug:locks (if available) or inspect var/lock/ manually.

Extension Points

  1. Custom Log Handlers Override getLogger() to inject custom handlers:

    protected function getLogger()
    {
        $logger = parent::getLogger();
        $logger->pushHandler(new CustomHandler());
        return $logger;
    }
    
  2. Add Command Metadata Extend BaseCommand to add custom metadata (e.g., tags, categories):

    protected function getMetadata()
    {
        return [
            'tags' => ['system', 'admin'],
            'category' => 'Maintenance',
        ];
    }
    
  3. Runtime Configuration Dynamically adjust settings via input arguments:

    protected function configure()
    {
        $this->addArgument('log-level', InputArgument::OPTIONAL, 'Override log level', 'info');
    }
    
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->setLogLevel($input->getArgument('log-level'));
    }
    

Performance Considerations

  • Locking Overhead: Avoid locking for fast, idempotent commands.
  • Bulk Processing: Use processItems() with chunking for large datasets to avoid memory issues:
    $this->processItems($items, function ($item) { /* ... */ }, 100); // Process 100 items at a time
    
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.
croct/coding-standard
croct/plug-php
nqxcode/phpmorphy
boundwize/pyrameter
testo/facade
develia/commons
dmstr/symfony-system-resources-bundle
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
renatomarinho/laravel-page-speed
develia/geo-bundle
austinheap/laravel-database-encryption
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme