Este paquete facilita la ejecución de PHP al mismo tiempo. Detrás de escena, la concurrencia se logra bifurcando el proceso PHP principal en una o más tareas secundarias.
En este ejemplo, donde llamaremos a una API lenta imaginaria, los tres cierres se ejecutarán al mismo tiempo.
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
En este vídeo de YouTube explicamos cómo funciona el paquete internamente.
Invertimos muchos recursos en la creación de los mejores paquetes de código abierto. Puedes apoyarnos comprando uno de nuestros productos pagos.
Apreciamos mucho que nos envíe una postal desde su ciudad natal, mencionando cuál de nuestros paquetes está utilizando. Encontrarás nuestra dirección en nuestra página de contacto. Publicamos todas las postales recibidas en nuestro muro virtual de postales.
Este paquete requiere PHP 8 y las extensiones pcntl que están instaladas en muchos sistemas Unix y Mac de forma predeterminada.
pcntl solo funciona en procesos CLI, no en un contexto web. Se requiere posix para el manejo correcto de la terminación del proceso para Alpine Linux.
Puede instalar el paquete a través del compositor:
composer require spatie/fork
Puedes pasar tantos cierres como quieras run
. Se ejecutarán simultáneamente. La función run
devolverá una matriz con los valores de retorno de los cierres ejecutados.
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'
Si necesita ejecutar algún código antes o después de cada invocable pasado a run
, puede pasar un invocable a los métodos before
o after
. Este invocable pasado se ejecutará en el proceso hijo justo antes o después de la ejecución del invocable pasado para run
.
before
y after
en la tarea infantil Aquí hay un ejemplo en el que obtendremos un valor de la base de datos usando un modelo Laravel Eloquent. Para permitir que la tarea secundaria use la base de datos, es necesario volver a conectarse a la base de datos. El cierre pasado before
se ejecutará en ambas tareas secundarias que se crean para los cierres pasados para 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 (),
);
Si necesita realizar alguna limpieza en la tarea secundaria después de que se haya ejecutado el invocable, puede usar el método after
en una instancia de SpatieForkFork
.
before
y after
en la tarea principal. Si necesita permitir que el invocable se pase before
o after
ejecutarse en la tarea principal, entonces debe pasar ese invocable al argumento 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 (),
);
También puede pasar diferentes cierres para ejecutarlos en la tarea secundaria y principal.
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 (),
);
Todos los datos de salida se recopilan en una matriz y están disponibles tan pronto como todos los elementos secundarios terminan. En este ejemplo, $results
contendrá tres elementos:
$ results = Fork:: new ()
-> run (
fn () => ( new Api )-> fetchData (userId: 1 ),
fn () => ( new Api )-> fetchData (userId: 2 ),
fn () => ( new Api )-> fetchData (userId: 3 ),
);
El resultado también está disponible en las devoluciones de llamada after
, que se llaman cada vez que un niño termina y no al final:
$ 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 ,
);
Finalmente, los valores de retorno de las tareas secundarias se serializan utilizando el método serialize
integrado de PHP. Esto significa que puedes devolver cualquier cosa que normalmente puedas serializar en PHP, incluidos objetos:
$ result = Fork:: new ()
-> run (
fn () => new DateTime ( ' 2021-01-01 ' ),
fn () => new DateTime ( ' 2021-01-02 ' ),
);
De forma predeterminada, todos los invocables se ejecutarán en paralelo. Sin embargo, puedes configurar una cantidad máxima de procesos simultáneos:
$ results = Fork:: new ()
-> concurrent ( 2 )
-> run (
fn () => 1 ,
fn () => 2 ,
fn () => 3 ,
);
En este caso, las dos primeras funciones se ejecutarán inmediatamente y en cuanto finalice una de ellas, se iniciará también la última.
composer test
Consulte CHANGELOG para obtener más información sobre los cambios recientes.
Consulte CONTRIBUCIÓN para obtener más detalles.
Revise nuestra política de seguridad sobre cómo informar vulnerabilidades de seguridad.
La Licencia MIT (MIT). Consulte el archivo de licencia para obtener más información.