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

draw/process

draw/process is a Laravel/PHP package for running and managing external processes. It helps you start commands, capture output, handle errors, and control execution in a clean API—useful for queues, build tasks, and integrations that need shell tools.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require draw/process
    
    • Requires PHP 8.0+ and Laravel 8+ (implicitly via Symfony Process dependency).
  2. First Use Case Replace a native Symfony Process call with the package’s enhanced version:

    use Draw\Process\Process;
    
    $process = new Process(['php', 'artisan', 'queue:work', '--once']);
    $process->run();
    
    if (!$process->isSuccessful()) {
        Log::error('Queue worker failed: ' . $process->getErrorOutput());
    }
    
  3. Where to Look First

    • src/Process.php: Core class extending Symfony’s Process with Laravel-friendly methods.
    • tests/: Example test cases for edge cases (timeouts, output streaming).
    • README.md: Basic usage snippets (if available; otherwise, inspect Process class docs).

Implementation Patterns

Workflows

1. Background Job Orchestration

// In a Laravel Job
public function handle() {
    $process = new Process(['python', 'scripts/process_data.py', '--input', $this->inputFile]);
    $process->setTimeout(300); // 5-minute timeout
    $process->run();

    if ($process->isTimedOut()) {
        $this->release(60); // Retry after 1 minute
    } elseif (!$process->isSuccessful()) {
        $this->fail($process->getErrorOutput());
    }
}

2. Real-Time Output Streaming

// In a Livewire/Inertia component
$process = new Process(['ffmpeg', '-i', 'input.mp4', 'output.mp4']);
$process->run(function ($type, $buffer) {
    $this->emit('process-output', [
        'type' => $type === Process::OUT ? 'stdout' : 'stderr',
        'data' => $buffer,
    ]);
});

3. Process Chaining

// Chain commands (e.g., build + test)
$buildProcess = new Process(['npm', 'run', 'build']);
$testProcess = new Process(['npm', 'test']);

$buildProcess->run();
if ($buildProcess->isSuccessful()) {
    $testProcess->run();
    // Handle test results...
}

4. Laravel Artisan Integration

// Custom Artisan command
protected function execute(InputInterface $input, OutputInterface $output) {
    $process = new Process(['php', 'artisan', 'migrate', '--env=testing']);
    $process->setOutput($output); // Stream to Artisan's output
    $process->run();
}

5. Environment-Specific Commands

// Use config to switch commands per environment
$command = config('process.commands.backup');
$process = new Process(explode(' ', $command));
$process->run();

Integration Tips

  • Service Provider Binding Extend Laravel’s container to auto-resolve Process:

    // app/Providers/AppServiceProvider.php
    public function register() {
        $this->app->bind(Process::class, function () {
            return new \Draw\Process\Process([]);
        });
    }
    
  • Logging Decorator Wrap Process to log all executions:

    class LoggedProcess extends Process {
        public function run($callback = null) {
            Log::info('Running process: ' . $this->getCommandLine());
            return parent::run($callback);
        }
    }
    
  • Queue Job Wrapper Create a reusable job for subprocesses:

    namespace App\Jobs;
    
    use Draw\Process\Process;
    use Illuminate\Bus\Queueable;
    
    class RunProcessJob implements Queueable {
        use Dispatchable, InteractsWithQueue;
    
        public function __construct(
            public array $command,
            public int $timeout = 300,
        ) {}
    
        public function handle() {
            $process = new Process($this->command);
            $process->setTimeout($this->timeout);
            $process->run();
    
            if (!$process->isSuccessful()) {
                throw new \RuntimeException($process->getErrorOutput());
            }
        }
    }
    
  • Testing Mock Process in unit tests:

    $mockProcess = Mockery::mock(Process::class);
    $mockProcess->shouldReceive('run')->andReturn(null);
    $mockProcess->shouldReceive('isSuccessful')->andReturn(true);
    
    $this->app->instance(Process::class, $mockProcess);
    

Gotchas and Tips

Pitfalls

  1. Silent Process Failures

    • Issue: run() returns null on success but doesn’t throw exceptions.
    • Fix: Always check isSuccessful() or use mustRun():
      $process->mustRun(); // Throws \RuntimeException on failure
      
  2. Resource Leaks in Long-Running Processes

    • Issue: Processes may linger if not terminated (e.g., in Laravel queues).
    • Fix: Implement cleanup in terminate() or use Process::terminateAll():
      register_shutdown_function(function () {
          Process::terminateAll();
      });
      
  3. Environment Variable Pollution

    • Issue: Accidentally exposing sensitive env vars to subprocesses.
    • Fix: Explicitly set only required variables:
      $process->setEnv(['APP_ENV' => 'testing']); // Avoid `getenv()` leaks
      
  4. Cross-Platform Path Issues

    • Issue: Hardcoded paths (e.g., /tmp/file.log) fail on Windows.
    • Fix: Use storage_path() or sys_get_temp_dir():
      $process->setCommandLine([
          'touch', storage_path('app/temp/file.log')
      ]);
      
  5. Timeout Misconfiguration

    • Issue: Timeouts too short for slow commands (e.g., sleep 60 with setTimeout(10)).
    • Fix: Set realistic timeouts (e.g., 300 seconds for long tasks).
  6. Output Buffering

    • Issue: Large output may crash PHP (e.g., tail -f logs).
    • Fix: Stream output incrementally:
      $process->run(function ($type, $buffer) {
          file_put_contents('log.txt', $buffer, FILE_APPEND);
      });
      

Debugging Tips

  1. Inspect Process State

    $process->run();
    echo "Exit Code: " . $process->getExitCode();
    echo "Output: " . $process->getOutput();
    echo "Error: " . $process->getErrorOutput();
    
  2. Enable Debug Logging

    $process->setDebug(true); // Logs command execution to storage/logs/laravel.log
    
  3. Check for Zombie Processes

    ps aux | grep "php artisan"  # Manually inspect running processes
    
  4. Validate Command Line

    echo $process->getCommandLine(); // Verify the exact command being run
    

Extension Points

  1. Custom Process Decorators Extend Process to add domain-specific logic:

    class DatabaseBackupProcess extends Process {
        public function __construct() {
            parent::__construct(['mysqldump', '-u', 'root', 'database']);
        }
    
        public function backupTo(string $path) {
            $this->setCommandLine([
                'mysqldump', '-u', 'root', 'database', '>', $path
            ]);
        }
    }
    
  2. Hooks for Pre/Post Execution

    $process = new Process(['git', 'pull']);
    $process->onStart(function () {
        Log::info('Starting git pull...');
    });
    $process->onEnd(function ($exitCode) {
        Log::info("Git pull exited with code: {$exitCode}");
    });
    
  3. Laravel Event Integration Dispatch events for process lifecycle:

    $process = new Process(['composer', 'install']);
    event(new ProcessStarting($process));
    $process->run();
    event(new ProcessEnded($process));
    

Configuration Quirks

  1. Symfony Process Version Conflicts

    • Issue: Package may require symfony/process:^5.4 but Laravel uses 6.x.
    • Fix: Override in composer.json:
      "require": {
          "symfony/process": "^6.0"
      },
      "extra": {
          "laravel": {
              "dont-discover": ["draw/process"]
          }
      }
      
  2. Laravel’s Native Process Facade

    • Issue: Conflicts with Process facade from illuminate/process.
    • Fix: Use fully qualified class name:
      use
      
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.
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky