Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Middle Artisan

Як запускати зовнішні програми з Laravel через фасад Process і як це тестувати?

Фасад Process - обгортка над компонентом Symfony Process для запуску зовнішніх програм: git, ffmpeg, pg_dump, скриптів. Він замінює exec() і shell_exec() зручним API з тайм-аутами й тестуванням.

Запуск і результат:

use Illuminate\Support\Facades\Process;

$result = Process::run(['git', 'log', '--oneline', '-5']);

$result->successful();   // код завершення 0
$result->output();       // stdout
$result->errorOutput();  // stderr
$result->exitCode();

Масив аргументів замість рядка - головне правило безпеки. З масивом кожен аргумент передається окремо, без участі shell, і ін'єкція команд неможлива:

Process::run(['convert', $uploadedPath, '-resize', '800x', $outputPath]);   // безпечно
Process::run("convert {$uploadedPath} -resize 800x {$outputPath}");         // ін'єкція через назву файлу

Параметри:

Process::path(storage_path('exports'))
    ->timeout(120)              // за замовчуванням 60 секунд
    ->idleTimeout(30)           // без виводу довше - зупинити
    ->env(['PGPASSWORD' => $password])
    ->input($csv)
    ->run(['psql', '-c', '\copy items from stdin csv']);

Process::run($command)->throw();   // виняток при ненульовому коді

Асинхронно й паралельно:

$process = Process::start(['ffmpeg', '-i', $in, $out]);
// ... інша робота ...
$result = $process->wait();

[$first, $second] = Process::concurrently(function (Pool $pool) {
    $pool->path(base_path())->command(['npm', 'run', 'lint']);
    $pool->path(base_path())->command(['vendor/bin/pint', '--test']);
});

Тестування - без справжнього запуску:

Process::fake([
    '*ffmpeg*' => Process::result(output: 'done'),
    '*git*' => Process::result(errorOutput: 'fatal', exitCode: 128),
]);

// ... виклик коду ...

Process::assertRan(fn (PendingProcess $process) => $process->command[0] === 'ffmpeg');

Шаблони порівнюються з повним командним рядком, де аргументи масиву взяті в лапки, тому зручні шаблони з * з обох боків. Process::preventStrayProcesses() змушує тест падати, якщо запущено процес, для якого немає підробки, - тести ніколи не запустять справжній rm чи git push.

Де запускати: довгі процеси (конвертація відео, бекапи) - у черзі, а не у вебзапиті; тайм-аут процесу має бути меншим за тайм-аут задачі.

Докладніше в документації: Процеси

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання