本文へ移動
Laravel Tips

同時に動かす(並行処理)

時間のかかる、おたがいに関係のない処理を同時に動かして速くする、Concurrency の使い方とドライバー、結果の名前、タイムアウトを説明します。

並行処理(同時に動かすこと)は、時間のかかる仕事をいっせいに始めて、待ち時間を短くするしくみです。たとえば、3人で別々の掃除を同時に始めれば、1人で順番にやるより早く終わります。たがいに関係のない、遅い処理がいくつかあるときに、使えます。Laravel の Concurrency ファサード(Route::get() のように、クラス名と :: で機能を呼べる窓口)で、関数(クロージャ)を同時に動かせます。

しくみとドライバー#

Laravel は、渡された関数を、シリアライズ(文字などの形に変えて、あとで元に戻せるようにすること)して、一覧には出ない、隠れた Artisan コマンド(php artisan で動かすコマンド)へ送ります。そのコマンドが、関数を元に戻し、自分の PHP のプロセス(動いているプログラム)で動かします。動かし終わったら、結果をシリアライズして、元のプロセスへ返します。

Concurrency には、3つのドライバー(動かし方の種類)があります。process(はじめの設定)・fork・sync です。

ドライバー 説明
process はじめの設定。関数を別の PHP のプロセスで動かす
fork process より速い。PHP の CLI(ターミナルで動かすとき)でだけ使える
sync 同時には動かさず、元のプロセスで順番に動かす。テストのときに便利

fork は、process より速くなります。ただし、PHP は Web のリクエストの中ではフォーク(プロセスを複製すること)ができないので、CLI の中でしか使えません。使う前に、spatie/fork パッケージを入れます。

bash
composer require spatie/fork

sync は、おもにテストで使います。同時には動かさず、渡された関数を、元のプロセスで順番に動かします。

同時に動かす#

同時に動かすには、Concurrency ファサードの run メソッドを呼びます。run は、関数の配列を受け取り、それらを PHP の子のプロセス(元のプロセスから作られた、別のプロセス)で同時に動かします。

php
use Illuminate\Support\Facades\Concurrency;
use Illuminate\Support\Facades\DB;

[$userCount, $orderCount] = Concurrency::run([
    fn () => DB::table('users')->count(),
    fn () => DB::table('orders')->count(),
]);

ドライバーを決めるには、driver メソッドを使います。

php
$results = Concurrency::driver('fork')->run(...);

はじめのドライバーを変えたいときは、config:publish コマンドで、concurrency の設定ファイルを取り出して、その中の default を直します。

bash
php artisan config:publish concurrency

結果に名前を付ける#

結果を、順番ではなく、名前で取り出したいときは、キーを付けた配列(連想配列)で、関数を渡します。結果は、対応する関数と同じキーで返ります。

php
use Illuminate\Support\Facades\Concurrency;
use Illuminate\Support\Facades\DB;

$results = Concurrency::run([
    'users' => fn () => DB::table('users')->count(),
    'orders' => fn () => DB::table('orders')->count(),
]);

$userCount = $results['users'];
$orderCount = $results['orders'];

時間の制限(タイムアウト)#

process ドライバー(はじめの設定)のときは、run に時間の制限(タイムアウト)を渡せます。決めた秒数がすぎても終わらない処理は、止められます。

php
use Illuminate\Support\Facades\Concurrency;
use Illuminate\Support\Facades\DB;

[$userCount, $orderCount] = Concurrency::run([
    fn () => DB::table('users')->count(),
    fn () => DB::table('orders')->count(),
], timeout: 30);

分かりやすく書きたいときは、CarbonInterval(時間の長さを表すオブジェクト)も渡せます。

php
use Illuminate\Support\Facades\Concurrency;

use function Illuminate\Support\seconds;

Concurrency::run([...], timeout: seconds(30));

あとで同時に動かす#

関数を同時に動かしたいけれど、結果は要らないときは、defer メソッドが使えます。defer を呼んでも、すぐには動きません。ユーザーへ HTTP のレスポンス(サーバーが返す答え)を送ったあとに、Laravel が同時に動かします。

php
use App\Services\Metrics;
use Illuminate\Support\Facades\Concurrency;

Concurrency::defer([
    fn () => Metrics::report('users'),
    fn () => Metrics::report('orders'),
]);
メソッド 説明
run 関数を同時に動かし、結果を返す(timeout で時間の制限を決められる)
driver 使うドライバーを決める
defer レスポンスを送ったあとで、関数を同時に動かす(結果は受け取らない)

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧