digipolisgent/command-builder
PHP command builder to compose complex shell command strings fluently. Add flags/arguments, pipe output, and chain onSuccess/onFailure blocks to build conditional command groups for safe execution and readable CLI scripting.
Artisan commands) or event-driven workflows (e.g., queue jobs with post-execution logic).Symfony/Process) but adds declarative chaining for multi-step operations. Could integrate with:
onSuccess/onFailure triggering email/SMS).CommandBuilder output in Symfony/Process or exec()).shell_exec() or Process).use DigipolisGent\CommandBuilder\CommandBuilder;
use Symfony\Component\Process\Process;
$command = CommandBuilder::create('php artisan queue:work')
->onFailure('php artisan queue:failed')
->getCommand(); // Returns shell string
$process = new Process(explode(' ', $command));
$process->run();
| Risk Area | Severity | Mitigation Strategy |
|---|---|---|
| Shell Injection | High | Validate all dynamic arguments/flags. Use escapeshellarg() or Symfony/Process for safety. |
| Cross-Platform Issues | Medium | Test on target OS (e.g., Linux vs. Windows). Use Process::isSuccessful() for cross-platform checks. |
| Error Handling | Medium | Wrap CommandBuilder output in try-catch with Process for robust failure recovery. |
| Performance | Low | Minimal overhead; risk only in nested/complex pipelines. |
| Deprecation | High | Fork or replace if package stagnates. Prioritize for non-critical paths. |
Why not use Symfony/Process directly?
onSuccess/onFailure) or is Process sufficient?->pipeOutputTo()) a productivity win over manual string concatenation?Security Requirements:
Maintenance Plan:
spatie/laravel-command or custom solutions)?Use Case Scope:
onFailure retries (e.g., queue:failed handling).CommandBuilder chains on events (e.g., job.failed).exec()/shell_exec() calls with CommandBuilder to validate the DSL’s value.ShellCommandService).
class ShellCommandService {
public function buildCommand(string $baseCommand): string {
return CommandBuilder::create($baseCommand)->getCommand();
}
}
CommandBuilder (e.g., Command::build()).Symfony/Process:
$command = CommandBuilder::create('ls')->addFlag('a')->getCommand();
$process = new Process(explode(' ', $command));
$process->run();
--color=always) if cross-platform support is needed.exec() calls with CommandBuilder for complex pipelines.Symfony/Process for robust error handling and logging.ls fail?").Log::debug('Executing command:', ['command' => $builder->getCommand()]);
onSuccess/onFailure are binary; no partial failure handling.Symfony/Process for exit code inspection:
if (!$process->isSuccessful()) {
// Custom logic for exit code 127 (command not found), etc.
}
getCommand() output).Process in parallel:
$processes = collect($commands)->map(fn ($cmd) => new Process(explode(' ', $cmd)));
$processes->each(fn ($p) => $p->start());
ls vs. ffmpeg).| Failure Scenario | Impact | Mitigation |
|---|---|---|
| Shell Injection | Arbitrary code execution. | Validate inputs; use Process. |
| Command Not Found | Exit code 127. | Check $process->isSuccessful(). |
| Permission Denied | Exit code 126. | Run as expected user (e |
How can I help you explore Laravel packages today?