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

Process Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require symfony/process
    

    No additional configuration is required—just autoload via Composer.

  2. First Use Case: Execute a simple command and capture output:

    use Symfony\Component\Process\Process;
    use Symfony\Component\Process\Exception\ProcessFailedException;
    
    $process = new Process(['ls', '-la']);
    $process->run();
    
    if (!$process->isSuccessful()) {
        throw new ProcessFailedException($process);
    }
    
    echo $process->getOutput();
    
  3. Where to Look First:

    • Official Documentation (API reference, examples).
    • Process class methods: run(), getOutput(), isSuccessful(), getErrorOutput().
    • Environment handling: setEnv(), getEnv().

Implementation Patterns

Core Workflows

1. Command Execution with Output Capture

$process = new Process(['php', 'artisan', 'migrate']);
$process->run();

// Output handling
echo $process->getOutput(); // stdout
echo $process->getErrorOutput(); // stderr

2. Environment Variable Injection

$process = new Process(['./script.sh']);
$process->setEnv([
    'DB_HOST' => 'localhost',
    'APP_ENV' => 'production',
    'ARRAY_VAR' => ['val1', 'val2'], // Supported in v8.1.0+
]);
$process->run();

3. Real-Time Output Streaming

$process = new Process(['tail', '-f', 'logfile.log']);
$process->start();

while ($process->isRunning()) {
    echo $process->getOutput();
    usleep(100); // Throttle to avoid CPU overload
}

4. Timeout and Resource Limits

$process = new Process(['php', 'slow-script.php']);
$process->setTimeout(30); // 30 seconds
$process->run();

if ($process->isTimedOut()) {
    $process->stop();
}

5. Integration with Laravel Artisan

use Symfony\Component\Process\Process;

$command = 'php artisan queue:work --once';
$process = new Process(explode(' ', $command));

// Run in background (detached)
$process->start();

Laravel-Specific Patterns

1. Service Container Binding

// config/app.php
'bindings' => [
    Symfony\Component\Process\Process::class => function ($app) {
        return new Process(['php', 'artisan']);
    },
];

2. Command Bus Integration

use Symfony\Component\Process\Process;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;

class RunProcessJob implements ShouldQueue
{
    use Queueable;

    public function handle()
    {
        $process = new Process(['php', 'artisan', 'notify:users']);
        $process->run();
        $this->logProcessOutput($process);
    }
}

3. Environment-Agnostic Configs

// config/process.php
return [
    'default_env' => [
        'APP_ENV' => env('APP_ENV'),
        'APP_DEBUG' => env('APP_DEBUG', false),
    ],
    'commands' => [
        'migrate' => ['php', 'artisan', 'migrate'],
        'queue' => ['php', 'artisan', 'queue:work', '--once'],
    ],
];

4. Testing Subprocesses

use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;

public function testProcessExecution()
{
    $process = new Process(['php', 'artisan', 'list']);
    $process->mustRun();

    $this->assertStringContainsString('migrate', $process->getOutput());
}

Advanced Patterns

1. Pseudo-TTY Allocation (PTY)

$process = new Process(['bash']);
$process->setPty(true); // Enable interactive shell
$process->start();

$process->write('ls -la');
echo $process->getOutput();

2. Signal Handling

$process = new Process(['sleep', '10']);
$process->start();

if ($process->isRunning()) {
    $process->signal(SIGTERM); // Graceful shutdown
}

3. Cross-Platform Command Normalization

$command = Process::escapeArgumentList([
    'php',
    'artisan',
    'queue:work',
    '--once',
]);

4. Process Pooling

$processes = [];
for ($i = 0; $i < 5; $i++) {
    $process = new Process(['php', 'artisan', 'queue:work', '--once']);
    $process->start();
    $processes[] = $process;
}

foreach ($processes as $p) {
    $p->wait();
}

Gotchas and Tips

Common Pitfalls

  1. Environment Variable Limits (Windows)

    • Issue: Windows imposes a ~32KB limit on environment blocks.
    • Fix: Use setEnv() sparingly or split into multiple processes.
    • Workaround:
      if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
          $process->setEnv(['KEY' => 'value']); // Avoid arrays
      }
      
  2. Broken Pipes (Stdin/Stdout)

    • Issue: proc_open may fail silently on broken pipes (e.g., closed terminal).
    • Fix: Use mustRun() or check isSuccessful():
      $process->mustRun(); // Throws \RuntimeException on failure
      
  3. Array Environment Variables (Pre-v8.1.0)

    • Issue: Older versions may not handle ['KEY' => ['val1', 'val2']].
    • Fix: Upgrade to ^8.1.0 or flatten arrays manually:
      $process->setEnv(['KEY' => json_encode(['val1', 'val2'])]);
      
  4. PTY Mode on Windows

    • Issue: PTY allocation may fail on Windows.
    • Fix: Disable PTY or use WSL:
      if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
          $process->setPty(false);
      }
      
  5. Signal Handling Race Conditions

    • Issue: Signals like SIGTERM may not propagate immediately.
    • Fix: Add a small delay or poll isRunning():
      $process->signal(SIGTERM);
      usleep(500000); // 0.5s delay
      

Debugging Tips

  1. Log Raw Output

    $process = new Process(['ls', '/nonexistent']);
    $process->run();
    file_put_contents(
        storage_path('logs/process_debug.log'),
        $process->getOutput() . "\n" . $process->getErrorOutput()
    );
    
  2. Check Process Status

    if ($process->isRunning()) {
        echo "Process is still running...\n";
    } elseif ($process->isSuccessful()) {
        echo "Success!\n";
    } else {
        echo "Failed with exit code: " . $process->getExitCode() . "\n";
    }
    
  3. Enable Verbose Mode

    $process = new Process(['php', '-v', 'artisan', 'migrate']);
    
  4. Use proc_open Directly for Debugging

    $descriptors = [
        0 => ['pipe', 'r'], // stdin
        1 => ['pipe', 'w'], // stdout
        2 => ['pipe', 'w'], // stderr
    ];
    $process = proc_open('php artisan migrate', $descriptors, $pipes);
    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $returnValue = proc_close($process);
    

Configuration Quirks

  1. Environment Inheritance

    • By default, processes inherit the parent’s environment. Use setEnv() to override:
      $process->setEnv(['APP_ENV' => 'testing'], true); // Override all
      
  2. Working Directory

    • Set explicitly to avoid path issues:
      $process->setWorkingDirectory(base_path());
      
  3. **Shell

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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope