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 Extra Laravel Package

zenstruck/console-extra

Modular helpers to reduce boilerplate in Symfony console commands. Build invokable commands with auto-injected IO, arguments/options via attributes, and handy traits to run other commands or processes. Designed to mix and match features or power a shared base command.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Symfony CLI Integration: The package is optimized for Symfony Console (and Laravel via Symfony Bridge), making it a natural fit for CLI-heavy applications. Laravel’s Symfony integration (via symfony/console) ensures seamless adoption.
  • Modular Design: Features like InvokableServiceCommand, RunsCommands, and RunsProcesses are decoupled, allowing selective adoption (e.g., use IO without RunsProcesses).
  • Attribute-Driven Configuration: Replaces verbose configure() methods with PHP 8.0+ attributes, reducing boilerplate and improving readability.
  • Laravel Compatibility: While Laravel lacks native Symfony’s controller.service_arguments, the package’s InvokableServiceCommand can be adapted via Laravel’s service container (e.g., binding commands as services with bind()).

Integration Feasibility

  • Low Friction: Requires zero changes to existing Laravel CLI commands if using Symfony’s Command base class. For native Laravel Artisan commands, a wrapper trait/class can bridge the gap.
  • Dependency Overhead: Minimal (symfony/process only needed for RunsProcesses). No Laravel-specific conflicts.
  • Backward Compatibility: Supports Symfony 6.4+ and PHP 8.1+, aligning with Laravel’s LTS support (v10+).

Technical Risk

  • Laravel-Specific Gaps:
    • Service Injection: Laravel’s Artisan commands don’t natively support InvokableServiceCommand’s DI. Mitigation: Use Laravel’s bind() or a custom command resolver.
    • Event Dispatcher: CommandSummarySubscriber requires Symfony’s EventDispatcher. Mitigation: Implement a Laravel event listener or use Laravel’s terminating hook.
  • Attribute Limitations: Laravel’s Artisan commands use define() for configuration, not attributes. Mitigation: Hybrid approach (attributes + configure() fallback).
  • Process Handling: RunsProcesses relies on symfony/process. Mitigation: Laravel’s Process facade can replace it with minor adjustments.

Key Questions

  1. Adoption Scope:
    • Will this replace all Artisan commands, or only new ones? (Mixed adoption may require a migration strategy.)
  2. Laravel-Specific Workarounds:
    • How will service injection be handled for existing Artisan commands?
    • Can CommandSummarySubscriber be replicated with Laravel’s terminating middleware?
  3. Testing Impact:
    • Will existing CLI tests need updates (e.g., command invocation syntax)?
  4. Performance:
    • Does InvokableServiceCommand add measurable overhead vs. native Artisan commands?
  5. Team Buy-In:
    • Is the team comfortable with attribute-based configuration (vs. traditional configure())?

Integration Approach

Stack Fit

  • Laravel + Symfony Bridge: Leverage symfony/console (already included in Laravel) to avoid reinventing the wheel.
  • Hybrid Commands: For existing Artisan commands, create a base trait that:
    • Extends Zenstruck\Console\InvokableCommand for new commands.
    • Wraps legacy commands with a decorator pattern to enable IO/RunsCommands features.
  • Service Container Alignment:
    • Bind InvokableServiceCommand instances as Laravel services using bind().
    • Example:
      $app->bind(CreateUserCommand::class, function ($app) {
          return new CreateUserCommand($app->make(UserManager::class));
      });
      

Migration Path

  1. Phase 1: New Commands
    • Adopt InvokableServiceCommand for new CLI features (e.g., php artisan user:create).
    • Use attributes for configuration (e.g., #[Argument], #[Option]).
  2. Phase 2: Legacy Wrappers
    • Create a LegacyCommandAdapter trait to retroactively add IO/RunsCommands to existing Artisan commands.
    • Example:
      class LegacyUserCommand extends Command {
          use Zenstruck\Console\LegacyCommandAdapter; // Hypothetical wrapper
          use RunsCommands;
      
          protected function execute(InputInterface $input, OutputInterface $output): int {
              $this->runCommand('new:user:create', [$input->getArgument('email')]);
              return Command::SUCCESS;
          }
      }
      
  3. Phase 3: Full Migration
    • Replace execute() methods with __invoke().
    • Update tests to use the new attribute-based syntax.

Compatibility

  • Symfony Console: Fully compatible via Laravel’s symfony/console integration.
  • Laravel Artisan: Requires workarounds for service injection and event dispatching (see "Technical Risk").
  • PHP Attributes: Requires PHP 8.0+ (Laravel 8+). For older versions, use a compiler pass to convert attributes to configure() calls.

Sequencing

  1. Dependency Setup:
    • Install the package:
      composer require zenstruck/console-extra
      
    • Ensure symfony/process is installed (for RunsProcesses).
  2. Base Command Class:
    • Create a shared base class for all new commands:
      abstract class AppConsoleCommand extends InvokableServiceCommand {}
      
  3. Incremental Adoption:
    • Start with non-critical commands (e.g., logs, reports).
    • Gradually migrate core commands (e.g., migrations, queues).
  4. Testing:
    • Update CLI test suites to account for attribute-based configuration.
    • Verify RunsCommands/RunsProcesses work in CI/CD pipelines.

Operational Impact

Maintenance

  • Reduced Boilerplate: Attributes and traits eliminate repetitive configure()/execute() code, lowering maintenance burden.
  • Consistent Patterns: Enforces uniform command structure (e.g., IO injection, success/error handling).
  • Dependency Updates:
    • Monitor zenstruck/console-extra for Symfony version compatibility.
    • Laravel’s Symfony bridge may require updates if symfony/console changes.

Support

  • Debugging:
    • Improved: Attribute-based errors (e.g., missing arguments) are more explicit than configure() logic.
    • Challenges: Legacy commands wrapped with traits may obscure stack traces. Mitigation: Use try-catch blocks in adapters.
  • Documentation:
    • Update internal docs to reflect new command patterns (e.g., __invoke() vs. execute()).
    • Highlight Laravel-specific quirks (e.g., service binding).

Scaling

  • Performance:
    • Negligible overhead for InvokableCommand (similar to native Artisan).
    • RunsCommands/RunsProcesses add minimal runtime cost (process spawning is the bottleneck).
  • Concurrency:
    • Commands remain synchronous (no async support). For parallel tasks, use Laravel’s dispatchSync() or Process facade.
  • Resource Usage:
    • CommandSummarySubscriber adds ~100ms overhead per command (memory/duration tracking). Disable in high-throughput environments.

Failure Modes

Risk Impact Mitigation
Service Injection Failure Command breaks if service not bound. Use Laravel’s bind() with fallback.
Process Hangs RunsProcesses blocks indefinitely. Set timeouts in Process objects.
Attribute Parsing Errors Invalid attributes crash commands. Validate with PHPStan or tests.
Event Dispatcher Mismatch CommandSummarySubscriber fails. Implement Laravel event listener.
Backward Incompatibility Symfony 7 drops support. Pin version or upgrade Laravel.

Ramp-Up

  • Developer Onboarding:
    • Pros: Attributes make commands self-documenting (e.g., #[Argument] clarifies inputs).
    • Cons: Requires familiarity with PHP attributes and Symfony’s IO pattern.
  • Training:
    • Workshop: Demo migrating a legacy command to InvokableServiceCommand.
    • Cheat Sheet: List common patterns (e.g., IO usage, RunsCommands syntax).
  • Tooling:
    • IDE Support: PHPStorm/WebStorm auto-completes attributes (e.g., #[Option]).
    • Static Analysis: PHPStan rules to catch misconfigured attributes.

Rollback Plan

  1. Partial Rollback:
    • Revert specific commands to legacy execute() while keeping others migrated.
  2. Fallback Mechanisms:
    • **Trait
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.
bugban/php-sdk
littlerocket/job-queue-bundle
graham-campbell/flysystem
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
directorytree/opensearch-client
directorytree/opensearch-adapter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php