symfony/process
Symfony Process executes system commands in isolated subprocesses with robust control over input/output, environment variables, timeouts, signals, and errors. Ideal for running CLI tools safely, streaming output, and integrating background tasks in PHP apps.
shell_exec(), exec(), or proc_open() calls with a consistent, feature-rich API.
exec('docker build --build-arg ARRAY=' . json_encode($config), $output, $return);
with:
$process = new Process(['docker', 'build'], [
'--build-arg' => ['ARRAY=' . json_encode($config)],
]);
$process->run();
ProcessEvent::TERMINATED) and Symfony Messenger for async subprocesses.graph TD
A[Laravel App] -->|composer| B[symfony/process:^8.1]
B --> C[php:^8.1]
B --> D[symfony/polyfill:^1.26]
Process as a singleton or bind to interfaces (e.g., ProcessRunnerInterface).Process for CLI-driven tasks (e.g., php artisan deploy:docker).Process in a ShouldQueue job for async execution.| Risk Area | Mitigation | Severity |
|---|---|---|
| PHP 8.1+ Requirement | Laravel 10+ mandates PHP 8.1+. Downgrade to v8.0.x if needed (but lose array env vars). | Low |
| Windows Environment Limits | Bug #63611 throws InvalidArgumentException for >32KB env vars. Workaround: Split arrays or use platform-specific logic. |
Medium |
| Process Isolation | Bug #64347 fixes CGI/FastCGI leaks, but legacy apps may still expose request context. Use $process->setTimeout() and $process->disableOutput() to mitigate. |
Low |
| Cross-Platform Quirks | MSYS escaping fixes (bug #63164) resolve Windows path issues. Test on all target OSes (e.g., GitHub Actions matrix). | Medium |
| Async/Concurrency | No built-in concurrency (use Laravel Queues or ReactPHP for parallel processes). |
Low |
| Security | CVE-2026-24739 (MSYS escaping) is patched. Validate subprocess commands (e.g., Str::of($command)->contains([';', '&&'])). |
Critical |
Process::mustRun()) or batch processing (e.g., Process::run())?Retryable trait or a custom decorator.proc_open resource exhaustion).ProcessPool service wrapper.Process::getOutput() + Laravel’s Log::info().Process with Prometheus client.Process-backed commands (e.g., php artisan deploy:build).Process in a job (e.g., RunDockerBuildJob) for async execution.ProcessEvent for pre/post-execution hooks.ProcessTestCase or mock Process with createMock(Process::class).Process to a custom interface (e.g., ProcessRunner) for testability.RunProcessMessage (v7.3+) for async workflows.['BUILD_ARGS' => ['--arg1', '--arg2']]).shell_exec in GitHub Actions/GitLab CI with Process for consistency.| Phase | Action | Tools/Examples |
|---|---|---|
| Assessment | Audit existing subprocess calls (e.g., exec(), shell_exec(), proc_open()). |
grep -r "exec|shell_exec|proc_open" app/ |
| Pilot | Replace 1–2 critical subprocesses (e.g., Docker builds, FFmpeg transcoding) with Process. |
php<br>// Before<br>exec('docker build ...');<br><br>// After<br>$process = new Process(['docker', 'build']);<br>$process->run();<br> |
| Refactor | Create a ProcessService facade to centralize logic (e.g., timeouts, logging). |
php<br>class ProcessService {<br> public function run(Process $process): string {<br> $process->run();<br> return $process->getOutput();<br> }<br>}<br> |
| Testing | Mock Process in unit tests. Use ProcessTestCase for integration tests. |
php<br>public function testProcess() {<br> $process = $this->getMockBuilder(Process::class)<br> ->disableOriginalConstructor()<br> ->onlyMethods(['run'])<br> ->getMock();<br> $process->expects($this->once())->method('run');<br>}<br> |
| Deployment | Update composer.json to symfony/process:^8.1. Test on all target OSes (Windows/Linux/macOS). |
json<br>"require": {<br> "symfony/process": "^8.1"<br>}<br> |
| Optimization | Profile subprocess performance (e.g., Process::getExitCodeTime()). Implement retry logic for flaky commands. |
php<br>use Symfony\Component\Process\Exception\ProcessFailedException;<br>try {<br> $process->mustRun();<br>} catch (ProcessFailedException $e) {<br> if ($e->getProcess()->getExitCode() === 137) { // SIGKILL<br> retry();<br> }<br>}<br> |
symfony/process:^8.1 (PHP 8.1+).symfony/process:^7.4 (PHP 8.0+).symfony/process:^6.4 (PHP 7.4+).How can I help you explore Laravel packages today?