這個套件使得並發運行 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)。請參閱許可證文件以獲取更多資訊。