Запуск команд в Laravel c использованием Процессов
Laravel построил фасад вокруг высокоэффективного компонента Symfony Process позволяющего выполнять команды вне среды Laravel.
Процессы позволяют командам оболочки, таким как grep
, и командам, которые вызывают внешние службы, такие как GitHub, выполняться асинхронно без потенциального нарушения определённого потока выполнения из-за синхронной природы PHP. Это происходит в режиме реального времени, с обратными вызовами и обработкой исключений.
Давайте рассмотрим, что это означает, с помощью базового примера кода ниже:
use Illuminate\Support\Facades\Process;
$result = Process::run('ls -la');
return $result->output();
В приведённом выше коде фасад Process вызывается и используется для запуска команды Linux ls
, выводящая список всех файлов в каталоге, включая скрытые файлы, которые затем распечатываются.
Предварительные требования
- Знания PHP
- PHP 8.1
- Composer установленный глобально
- Postman или curl
- Опыт работы с Laravel и с командной строкой будут полезны, но не обязательны.
Варианты использования
Запуск команд CLI: Команды CLI представляют собой текстовые пользовательские интерфейсы, используемые для запуска команд и взаимодействия с компьютерными файлами и функциями. Процессы позволяют запускать команды CLI, подобные приведённому выше примеру, в приложении Laravel.
Асинхронные команды: Процессы могут выполняться асинхронно, не прерывая другие функции приложения Laravel. Кроме того, выходные данные асинхронного процесса всё ещё могут быть выведены без прерывания процесса.
Конвейеризация/piping нескольких процессов: Конвейеризация нескольких команд может пригодиться, когда вы хотите, чтобы более поздняя команда выполнялась после завершения предыдущей. С Процессами несколько команда, таких как, например, приведённая ниже, могут запускаться и выполняться синхронно.
$result = Process::pipe(function (Pipe $pipe) {
$pipe->command('ls -la');
$pipe->command('grep -i "PHP"');
});
Как видно, первой запускаемой командой является команда ls -la
, которая выводит список файлов в каталоге, а затем команда grep -i "PHP"
для проверки и извлечения файлов, содержащих текст PHP
.
Параллельные функции: Параллельными задачами можно управлять одновременно с использованием Процесса. Это позволяет одновременно запускать несколько команд с использованием пользовательского пула функции. С помощью функции pool()
команды запускаются как автономные и выполняются асинхронно.
Ниже приведён пример запуска нескольких сценариев для импорта файлов.
use Illuminate\Process\Pool;
use Illuminate\Support\Facades\Process;
$pool = Process::pool(function (Pool $pool) {
$pool->path(__DIR__)->command('bash import-1.sh');
$pool->path(__DIR__)->command('bash import-2.sh');
$pool->path(__DIR__)->command('bash import-3.sh');
})->start(function (string $type, string $output, int $key) {
// ...
});
$results = $pool->wait();
Тестирование: Процессы, как все пакеты Laravel, могут получить доступ к Faker
для запуска командных тестов в среде Laravel. Использование фейковых Процессов может заставить Laravel использовать фиктивные данные для запуска команды и возврата данных.
Создание шаблона приложения Laravel
Чтобы проверить возможности Процессов в Laravel, сначала нужно установить и настроить приложение Laravel, а затем установить в проекте пакет Symfony Process. Создайте новый проект, используя приведённую ниже команду.
composer create-project laravel/laravel laravel_processes
Когда установка будет завершена, перейдите в каталог и запустите приложение с помощью следующих команд.
cd laravel_processes
php artisan serve
Ваше приложение должно работать по адресу http://localhost:8000
.
Затем в новом сеансе терминала установите пакет Symfony Process, используя приведённую ниже команду.
composer require symfony/process
Добавление поддержки процессов
По умолчанию для запуска процесса требуется, чтобы функция run()
запускала синхронные функции в среде Laravel, а функция start()
зарезервирована для асинхронных функций. В ходе этого руководства мы разберём это, а пока создайте базовую функцию используя тестовый контроллер.
Создание контроллера
Контроллер будет содержать функции, которые при запуске запускают заложенные в них функции процесса. Чтобы сгенерировать контроллер, выполните приведённую ниже команду.
php artisan make:controller ProcessController
Это создаст файл app/Http/Controllers/ProcessController.php
. Откройте файл и замените существующий код приведённым ниже кодом.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Process;
class ProcessController extends Controller
{
public function test() {
$result = Process::run('ls -la');
return $result->output();
}
}
Создание маршрута
Теперь, когда создан контроллер для вызова функции процесса, можем создать маршрут для запуска контроллера. Для этого перейдите в routes/api.php
и добавьте новый маршрут GET
, добавив следующий код в конец файла.
Route::get("/test", [App\Http\Controllers\ProcessController::class, 'test']);
Тестирование приложения
Тестирование можно выполнить с помощью команды curl
, выполнив приведённую ниже команду.
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://127.0.0.1:8000/api/test
Вы должны увидеть вывод, аналогичный приведённому ниже примеру.
HTTP/1.1 200 OK
Host: 127.0.0.1:8001
Date: Fri, 16 Jun 2023 12:10:53 GMT
Connection: close
X-Powered-By: PHP/8.1.18
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, private
Date: Fri, 16 Jun 2023 12:10:53 GMT
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
Access-Control-Allow-Origin: *
total 20
drwxrwxr-x 2 settermjd settermjd 4096 Jun 1 18:12 .
drwxrwxr-x 13 settermjd settermjd 4096 Jun 16 14:08 ..
-rw-rw-r-- 1 settermjd settermjd 603 Jun 1 18:12 .htaccess
-rw-rw-r-- 1 settermjd settermjd 0 Jun 1 18:12 favicon.ico
-rw-rw-r-- 1 settermjd settermjd 1710 Jun 1 18:12 index.php
-rw-rw-r-- 1 settermjd settermjd 24 Jun 1 18:12 robots.txt
Обработка ошибок
С помощью Процессов ошибки могут быть зарегистрированы в Laravel. Затем эти ошибки можно обработать внутренне или передать пользователю приложения. Это эффективно, потому что можно запускать внешние команды, и их результаты могут повлиять на поток активности в приложении Laravel, или ошибка просто регистрируется.
В приведённом ниже примере мы попытаемся инициировать процесс, который завершиться ошибкой. Это выведет ответ об ошибке, полученный от CLI.
В app/Http/Controllers/ProcessController.php
создайте новую функцию с именем error()
. Затем включите функцию errorOutput()
в обречённый на неудачу процесс, определив её следующим образом.
public function error() {
$result = Process::run("i-dont-exit");
return $result->errorOutput();
}
Затем добавьте маршрут для проверки ответа об ошибке в route/api.php
.
Route::get('/error-handling', [ProcessController::class, 'error']);
Затем приступайте к тестированию функции с помощью curl
.
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://127.0.0.1:8000/api/error-handling
В приведённом выше коде функция errorOutput()
использовалась для вывода ошибки, полученной от процесса. Результатом, подобным приведённому ниже, должна быть обратная связь, которую вы получаете от терминала.
sh: i-dont-exist: command not found
Также для тестирования можно использовать Postman
Вот как запускать команды в Laravel с помощью Процессов
В этой статье мы рассмотрели, что такое Процесс в Laravel, варианты его использования, а также как запускать и обрабатывать внешние команды и возвращать ошибки. Вы можете подробно изучить другие компоненты Symfony, которые позволяют эффективно программировать на Laravel. Я надеюсь, что вы используете Процессы для проверки ваших CLI команд, чтобы получить соответствующие данные для лучшего программирования.