phar-io/executor
phar-io/executor is a small PHP library for safely running external commands and processes. It builds and executes command lines, captures output and exit codes, and helps integrate tooling and CLI binaries into PHP applications and test suites.
Installation Add the package via Composer:
composer require phar-io/executor
No additional configuration is required—it’s a lightweight, dependency-free package.
First Use Case: Executing a Simple Command
Use the PharIo\Executor\Executor class to run shell commands directly from PHP:
use PharIo\Executor\Executor;
$executor = new Executor();
$output = $executor->execute('ls -la', [], null, null);
echo $output;
Where to Look First
Artisan commands, Console/Kernel.php, or service providers.Running CLI Commands in Artisan Commands
use PharIo\Executor\Executor;
class DeployCommand extends Command
{
protected $signature = 'deploy:run';
protected $description = 'Run deployment scripts';
public function handle()
{
$executor = new Executor();
$output = $executor->execute('git pull && php artisan migrate', [], null, null);
$this->info($output);
}
}
Capturing Output and Errors
Use the Output and ErrorOutput streams to log results:
$output = new \Symfony\Component\Process\BufferedOutput();
$errorOutput = new \Symfony\Component\Process\BufferedOutput();
$executor->execute('php artisan queue:work', [], $output, $errorOutput);
$this->info("Output: " . $output->getOutput());
$this->error("Errors: " . $errorOutput->getOutput());
Environment-Specific Commands
Dynamically build commands based on Laravel’s .env:
$command = env('APP_ENV') === 'production'
? 'php artisan queue:work --daemon'
: 'php artisan queue:work';
$executor->execute($command, [], null, null);
Integration with Laravel’s Process Facade While not native, wrap the executor in a helper:
if (!class_exists('ProcessExecutor')) {
class ProcessExecutor {
public static function run(string $command) {
$executor = new Executor();
return $executor->execute($command, [], null, null);
}
}
}
Usage:
ProcessExecutor::run('php artisan optimize');
No Symfony Process Dependency
Unlike Symfony/Process, this package doesn’t support streams or signals natively. For advanced use cases (e.g., timeouts, signals), consider:
// Fallback to Symfony/Process if needed
$process = new \Symfony\Component\Process\Process(['ls', '-la']);
$process->run();
Output Handling Quirks
execute() method returns a string, not a Process object. For structured output, parse manually or use Symfony’s BufferedOutput.Process, you can’t stream output line-by-line without buffering.Security Risks
$safeCommand = escapeshellcmd($userInput);
$executor->execute($safeCommand, [], null, null);
env() or encrypted storage.Cross-Platform Issues
dir (Windows) vs. ls (Linux) may break. Use Laravel’s Str::contains() or config('app.os') to adapt:
$command = config('app.os') === 'windows' ? 'dir' : 'ls';
Log Raw Output Redirect output to a file for debugging:
file_put_contents(storage_path('logs/command.log'), $output);
Check Exit Codes
The package doesn’t expose exit codes directly. Use exec() as a fallback if needed:
exec($command, $output, $exitCode);
$this->error("Failed with exit code: $exitCode");
Timeouts The package lacks built-in timeouts. Implement a wrapper:
$start = microtime(true);
$executor->execute($command, [], null, null);
if (microtime(true) - $start > 30) { // 30s timeout
throw new \RuntimeException('Command timed out');
}
Custom Output Handlers Extend the executor to support callbacks:
class CallbackExecutor extends Executor {
public function executeWithCallback(string $command, array $env, ?callable $outputCallback) {
$output = $this->execute($command, $env, null, null);
if ($outputCallback) $outputCallback($output);
return $output;
}
}
Laravel Service Provider Bind the executor to the container for dependency injection:
$this->app->singleton(Executor::class, function () {
return new Executor();
});
Usage in controllers/commands:
use Illuminate\Support\Facades\App;
$executor = App::make(Executor::class);
Event Dispatching Trigger Laravel events on command success/failure:
$output = $executor->execute($command, [], null, null);
if (str_contains($output, 'error')) {
event(new CommandFailed($command));
}
How can I help you explore Laravel packages today?