rapotor/console-bundle
A console bundle for Rapotor applications that adds structured command-line tooling: register CLI commands, run them from a single framework-integrated entry point, and keep terminal tasks consistent and easy to extend. Lightweight and straightforward to wire into existing apps.
Architecture fit — poor as a dependency, good as a pattern.
rapotor/console-bundle is a Symfony2 Bundle, not a Laravel package. It ships the Symfony2 conventions a TPM should look for and expect to conflict: a *Bundle class, DependencyInjection/*Extension, Resources/config/services.yml, and hard assumptions about the Symfony kernel, event dispatcher, and container. Laravel has no bundle system, no AppKernel, and package discovery via extra.laravel.providers is absent. The capability it describes — invoking a console command from inside application code — is native to Laravel via Artisan::call(), Artisan::output(), $this->call() inside commands, and the Illuminate\Contracts\Console\Kernel contract. There is no architectural gap this package fills in a Laravel codebase.
Integration feasibility — effectively zero as-is; high as a reference. The realistic paths are:
composer require rapotor/console-bundle in a Laravel app: not viable. Symfony 2.x version constraints collide with Laravel's symfony/console ^5/^6/^7 and with PHP 8.x. Expect solver failure, not a subtle runtime bug — which is at least a fast failure.Artisan::call() with output buffering and exit-code capture.Technical risk — high, concentrated in abandonment. 26 stars, 0 dependents, score 2.64. Zero dependents is the strongest signal here: no downstream project has validated this against a real workload, and no one is filing issues that would surface breakage. The package is PHP 5.3–5.6 era, likely PSR-0 autoloading, no visible CI, no security response process, and no PHP 8 compatibility. Adopting it means owning the entire maintenance surface from day one.
Secondary risk is inherent to the capability, not the code: executing console commands from application code is an injection and denial-of-service surface. Any user-influenced argument reaching a command invocation needs an allowlist, strict argument validation, and a hard timeout. Commands that shell out inherit the web process's privileges.
Key questions for the package owner / sponsor:
Artisan::call() plus Artisan::output() does not already satisfy? If the answer is "run Symfony2 commands from a legacy app," this package belongs to that app's migration, not to our Laravel estate.BufferedOutput, Process, queue jobs), not to this bundle.Verdict: reject as a dependency; retain as a design reference. Score it as an artifact of a pre-Artisan-facade era, not as a candidate component.
Stack fit — none directly; total via substitution.
Laravel already depends on symfony/console. The mapping is mechanical:
| Bundle concept | Laravel native equivalent |
|---|---|
| Run command from app code | Artisan::call('cmd', $args) |
| Capture output | Artisan::output() or a BufferedOutput instance |
| Exit code | Return value of Artisan::call() |
| Long-running / detached | Artisan::queue() on a queue driver, or symfony/process |
| Command registry | Console\Kernel::$commands and auto-discovery |
Migration path.
For a Symfony2 → Laravel migration, do not carry the bundle across. Replace each call site with Artisan::call() during the port, and let the bundle die with the old application. For a Laravel app evaluating this package, the migration is "write a small internal service" — a CommandRunner class with allowlisting, timeout, output capture, and structured logging — and treat the bundle only as evidence that the pattern was once needed.
Compatibility. Hard blockers: PHP version floor (5.x era syntax vs. Laravel 10/11 requiring PHP 8.1+), Symfony 2.x constraints, and PSR-0 autoloading. There is no compatibility matrix to negotiate — this is a clean incompatibility, which is preferable to a partial one that fails in production.
Sequencing.
CommandRunner against Artisan::call() + BufferedOutput; verify output capture, exit codes, and failure behavior against two real commands.No phase requires the vendor package. Do not add it to composer.json at any point.
Maintenance. Zero upstream maintenance. If the code is forked, the team inherits PHP 8 compatibility, security patching, and Symfony/Laravel version tracking forever. Against a ~30-line native replacement, the carrying cost is indefensible.
Support. No maintainer activity, no issue triage, no release cadence, 0 dependents to consult. Internal escalations terminate at the team that chose it. Budget for that explicitly if the decision is overridden.
Scaling. In-process command execution occupies a PHP-FPM worker for the duration of the command. A 30-second command invoked per request is a self-inflicted capacity incident: worker pool exhaustion, request queuing, and cascading timeouts under load. Any command exceeding a few hundred milliseconds must go to a queue with its own worker pool and concurrency limit. Output buffering is also a memory concern — a chatty command writing to an in-memory buffer can breach memory_limit before the timeout fires.
Failure modes to instrument for:
Each of these needs an explicit guard in the internal replacement: mandatory exit-code check, structured result object, hard timeout, allowlist, and audit log.
Ramp-up. Low. Artisan::call() is common Laravel idiom and most mid-level developers already know it; the allowlist and timeout policy are the only novel design surface. Realistically a one-day onboarding, versus the unbounded cost of teaching a team an abandoned Symfony2 bundle's internals.
Recommendation. Decline the dependency, cite the Symfony2/Laravel incompatibility and zero-dependents risk, and fund the half-day spike to build the native equivalent. The package's value to us is entirely as confirmation that this pattern is wanted — a need Laravel has already met.
How can I help you explore Laravel packages today?