这个包使得并发运行 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 进程,不适用于 Web 上下文。正确处理 Alpine Linux 的进程终止需要 posix。
您可以通过 Composer 安装该软件包:
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 模型从数据库中获取值。为了让子任务使用DB,需要重新连接DB。传递给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 (),
);
如果您需要在可调用程序运行后在子任务中执行一些清理,您可以在SpatieForkFork
实例上使用after
方法。
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
请参阅变更日志以了解有关最近更改内容的更多信息。
详细信息请参阅贡献。
请查看我们的安全政策,了解如何报告安全漏洞。
麻省理工学院许可证 (MIT)。请参阅许可证文件以获取更多信息。