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

Command Chaining Bundle Laravel Package

akmaks/command-chaining-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require akmaks/command-chaining-bundle
    
  2. Configure Chains Create config/packages/akmaks_command_chaining.yaml with a basic chain definition:

    parameters:
        chains:
            App\Console\MasterCommand:
                - App\Console\FirstChainCommand
                - App\Console\SecondChainCommand
    
  3. Implement CommandChainingInterface For master commands (entry points):

    use Akmaks\CommandChainingBundle\Command\CommandChainingInterface;
    
    class MasterCommand extends Command implements CommandChainingInterface {
        public function isMasterCommand(): bool { return true; }
    }
    

    For chain commands (sub-commands):

    class FirstChainCommand extends Command implements CommandChainingInterface {
        public function isMasterCommand(): bool { return false; }
    }
    
  4. Run the Master Command

    php artisan your:master-command
    

First Use Case: Batch Processing

Chain commands for sequential data processing (e.g., generate-reports, send-emails, cleanup-temp-files). Define them in the config and trigger via a single master command.


Implementation Patterns

Workflow: Command Orchestration

  1. Define Chains Group related commands in config/packages/akmaks_command_chaining.yaml:

    parameters:
        chains:
            App\Console\DeployCommand:
                - App\Console\BackupCommand
                - App\Console\MigrateCommand
                - App\Console\RestartServicesCommand
    
  2. Master Command Logic Use the master command to handle pre/post-chain logic (e.g., logging, validation):

    protected function execute(InputInterface $input, OutputInterface $output): int {
        $output->writeln('Starting deployment...');
        // Chain execution handled automatically
        return Command::SUCCESS;
    }
    
  3. Chain Command Dependencies Pass shared data between commands via Symfony’s Application or Input:

    // In MasterCommand:
    $this->getApplication()->find('backup')->run(new ArrayInput(['--path' => '/backup']), $output);
    
  4. Conditional Chaining Dynamically modify chains based on input:

    parameters:
        chains:
            App\Console\DynamicCommand:
                {% if app.environment == 'prod' %}
                - App\Console\ProdBackupCommand
                {% else %}
                - App\Console\DevBackupCommand
                {% endif %}
    

Integration Tips

  • Event Listeners: Attach listeners to master commands for cross-cutting concerns (e.g., logging, metrics).
  • Artisan Callbacks: Use post-command hooks to validate chain results:
    $this->getApplication()->get('console')->addListener(ConsoleEvents::COMMAND, function ($event) {
        if ($event->getCommandName() === 'your:master-command') {
            // Post-chain logic
        }
    });
    
  • Testing: Mock the CommandChainingInterface in unit tests to verify chain behavior:
    $this->expectsOutput('Chain executed successfully');
    $this->artisan('your:master-command')->assertExitCode(0);
    

Gotchas and Tips

Pitfalls

  1. Circular Dependencies Avoid defining chains where A depends on B, and B depends on A. The bundle does not detect cycles.

  2. Command Registration Order Ensure all chain commands are registered in the Symfony kernel before the master command. Use boot() in a bundle or service provider if needed.

  3. Input/Output Isolation Chain commands share the same Input/Output by default. Use --quiet or custom streams to isolate output:

    php artisan your:master-command --quiet
    
  4. Configuration Overrides The YAML config is loaded once at bootstrap. For dynamic chains, use a service to generate the config array programmatically:

    $container->setParameter('chains', $dynamicChainConfig);
    

Debugging

  • Verbose Mode: Enable debug output for chain execution:
    php artisan your:master-command --verbose
    
  • Log Chain Execution: Extend the bundle’s logger to track command flow:
    // In a service provider:
    $this->container->get('logger')->info('Chain started', ['command' => $masterCommand]);
    

Extension Points

  1. Custom Chain Resolvers Override CommandChainingResolver to implement dynamic chain resolution (e.g., database-backed chains):

    class DatabaseChainResolver implements CommandChainingResolverInterface {
        public function resolve(string $masterCommand): array {
            return $this->fetchFromDatabase($masterCommand);
        }
    }
    
  2. Pre/Post-Execution Hooks Extend the bundle’s CommandChainExecutor to add hooks:

    $executor->addPreExecuteHook(function ($command) {
        // Pre-execution logic
    });
    
  3. Parallel Execution Use Symfony’s Process component to run chain commands in parallel (not natively supported):

    foreach ($chainCommands as $command) {
        $process = new Process(['php', 'bin/console', $command]);
        $process->start();
    }
    

Pro Tips

  • Idempotency: Design chain commands to be idempotent (safe to re-run).
  • Error Handling: Use try-catch in master commands to halt chains on failure:
    try {
        $this->getApplication()->find('backup')->run($input, $output);
    } catch (Exception $e) {
        $output->writeln('<error>Backup failed. Aborting chain.</error>');
        return Command::FAILURE;
    }
    
  • Performance: For long chains, use --no-debug to skip verbose output during execution.
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui