Этот пакет упрощает одновременный запуск PHP. За кулисами параллелизм достигается путем разделения основного процесса PHP на одну или несколько дочерних задач.
В этом примере, где мы собираемся вызвать воображаемый медленный API, все три замыкания будут выполняться одновременно.
use Spatie Fork Fork ;
$ results = Fork:: new ()
-> run (
fn () => ( new Api )-> fetchData (userId: 1 ),
fn () => ( new Api )-> fetchData (userId: 2 ),
fn () => ( new Api )-> fetchData (userId: 3 ),
);
$ results [ 0 ]; // fetched data of user 1
$ results [ 1 ]; // fetched data of user 2
$ results [ 2 ]; // fetched data of user 3
В этом видео на YouTube мы объясняем, как пакет работает внутри.
Мы вкладываем много ресурсов в создание лучших в своем классе пакетов с открытым исходным кодом. Вы можете поддержать нас, купив один из наших платных продуктов.
Мы очень признательны вам за отправку нам открытки из вашего родного города с указанием того, какой из наших пакетов вы используете. Наш адрес вы найдете на странице контактов. Все полученные открытки мы публикуем на нашей виртуальной стене открыток.
Для этого пакета требуется PHP 8 и расширения pcntl, которые по умолчанию установлены во многих системах Unix и Mac.
pcntl работает только в процессах CLI, а не в веб-контексте. posix необходим для правильной обработки завершения процесса в Alpine Linux.
Вы можете установить пакет через композитор:
composer require spatie/fork
Вы можете передать столько замыканий, сколько run
. Они будут проводиться одновременно. Функция run
вернет массив с возвращаемыми значениями выполненных замыканий.
use Spatie Fork Fork ;
$ results = Fork:: new ()
-> run (
function () {
sleep ( 1 );
return ' result from task 1 ' ;
},
function () {
sleep ( 1 );
return ' result from task 2 ' ;
},
function () {
sleep ( 1 );
return ' result from task 3 ' ;
},
);
// this code will be reached this point after 1 second
$ results [ 0 ]; // contains 'result from task 1'
$ results [ 1 ]; // contains 'result from task 2'
$ results [ 2 ]; // contains 'result from task 3'
Если вам нужно выполнить некоторый код до или после каждого вызываемого объекта, переданного в run
, вы можете передать вызываемый объект методам before
или after
. Этот переданный вызываемый объект будет выполнен в дочернем процессе непосредственно до или после выполнения вызываемого объекта, переданного в run
.
before
и after
в дочерней задаче Вот пример, в котором мы собираемся получить значение из базы данных, используя модель Laravel Eloquent. Чтобы дочерняя задача могла использовать БД, необходимо переподключиться к БД. Замыкание, переданное before
будет выполняться в обеих дочерних задачах, созданных для замыканий, переданных в run
.
use App Models User ;
use Illuminate Support Facades DB ;
use Spatie Fork Fork ;
Fork:: new ()
-> before ( fn () => DB :: connection ( ' mysql ' )-> reconnect ())
-> run (
fn () => User:: find ( 1 )-> someLongRunningFunction (),
fn () => User:: find ( 2 )-> someLongRunningFunction (),
);
Если вам нужно выполнить некоторую очистку дочерней задачи после запуска вызываемого объекта, вы можете использовать метод after
в экземпляре SpatieForkFork
.
before
и after
в родительской задаче. Если вам нужно передать вызываемый объект before
или after
запуска родительской задачи, вам необходимо передать этот вызываемый объект в parent
аргумент.
use App Models User ;
use Illuminate Support Facades DB ;
use Spatie Fork Fork ;
Fork:: new ()
-> before (
parent: fn () => echo ' this runs in the parent task '
)
-> run (
fn () => User:: find ( 1 )-> someLongRunningFunction (),
fn () => User:: find ( 2 )-> someLongRunningFunction (),
);
Вы также можете передавать различные замыкания для запуска в дочерней и родительской задаче.
use Spatie Fork Fork ;
Fork:: new ()
-> before (
child: fn () => echo ' this runs in the child task ' ,
parent: fn () => echo ' this runs in the parent task ' ,
)
-> run (
fn () => User:: find ( 1 )-> someLongRunningFunction (),
fn () => User:: find ( 2 )-> someLongRunningFunction (),
);
Все выходные данные собираются в массив и доступны, как только все дочерние элементы будут завершены. В этом примере $results
будет содержать три элемента:
$ results = Fork:: new ()
-> run (
fn () => ( new Api )-> fetchData (userId: 1 ),
fn () => ( new Api )-> fetchData (userId: 2 ),
fn () => ( new Api )-> fetchData (userId: 3 ),
);
Вывод также доступен в обратных вызовах after
, которые вызываются всякий раз, когда дочерний элемент завершает работу, а не в самом конце:
$ results = Fork:: new ()
-> after (
child: fn ( int $ i ) => echo $ i , // 1, 2 and 3
parent: fn ( int $ i ) => echo $ i , // 1, 2 and 3
)
-> run (
fn () => 1 ,
fn () => 2 ,
fn () => 3 ,
);
Наконец, возвращаемые значения дочерних задач сериализуются с использованием встроенного в PHP метода serialize
. Это означает, что вы можете возвращать все, что обычно можно сериализовать в PHP, включая объекты:
$ result = Fork:: new ()
-> run (
fn () => new DateTime ( ' 2021-01-01 ' ),
fn () => new DateTime ( ' 2021-01-02 ' ),
);
По умолчанию все вызываемые объекты будут выполняться параллельно. Однако вы можете настроить максимальное количество одновременных процессов:
$ results = Fork:: new ()
-> concurrent ( 2 )
-> run (
fn () => 1 ,
fn () => 2 ,
fn () => 3 ,
);
В этом случае первые две функции будут запущены сразу, а как только одна из них завершится, запустится и последняя.
composer test
Пожалуйста, посетите CHANGELOG для получения дополнительной информации о том, что изменилось за последнее время.
Пожалуйста, смотрите ВКЛАД для получения подробной информации.
Пожалуйста, ознакомьтесь с нашей политикой безопасности, чтобы узнать, как сообщать об уязвимостях безопасности.
Лицензия MIT (MIT). Дополнительную информацию см. в файле лицензии.