- カテゴリ: helper
- 掲載バージョン: Laravel 12・PHP 8.4
- 名前空間 / FQCN / コマンド:
dispatch()(グローバル関数) - 関連:
Bus::dispatch/dispatch_sync/php artisan queue:work/ ジョブクラスのdispatch()メソッド - 変更履歴: Laravel 5系から存在。Laravel 8 以降は仕様ほぼ据え置き(ジョブのチェーンやディレイ指定など PendingDispatch 経由の機能が充実)。
要点(TL;DR)
- 何に使うか:キュー用のジョブやコマンドバスの「コマンド」を、Laravelのキューへ投入する。
- 最低限の使い方:
dispatch(new App\Jobs\SendWelcomeMail($user)); - よくある罠
- キュー接続が
syncのままで「実は同期実行」になっている queue:workを動かしておらず、いつまで経ってもジョブが処理されないShouldQueueを実装しておらず、キューに積まれずその場で実行されてしまう
- キュー接続が
概要
dispatch は、Laravel が提供するグローバルヘルパ関数で、指定したジョブをキューへ投入する入り口です。App\Jobs\* に定義したジョブクラスや、ShouldQueue を実装したクラスを渡すと、設定されたキュー接続(database / redis / sqs など)に積まれます。
ジョブクラス側の ::dispatch() と機能はほぼ同じで、関数スタイルで書きたいときや、Facade に依存したくない場面で使われます。
構文 / シグネチャ
/**
* ジョブ/コマンドをバス経由でディスパッチする
*/
function dispatch(object $job): mixed;
引数
| 引数 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|
$job | object | ○ | なし | ディスパッチするジョブ/コマンド。通常は App\Jobs\* のインスタンス。ShouldQueue 実装でキューへ積まれる |
戻り値
- 通常は
Illuminate\Foundation\Bus\PendingDispatchもしくはジョブの戻り値(同期実行時) PendingDispatch経由で->onQueue(),->delay()などをチェーン指定可能
例外 / 副作用
- キュー接続の設定が不正な場合、
InvalidArgumentExceptionなどの例外 - ドライバが
sync以外の場合、キューバックエンド(DB / Redis / SQS 等)にレコードやメッセージを追加 sync実行やShouldQueue未実装時は、その場でhandle()が実行され、その中で発生した例外がそのままスローされる
使用例
最小例
ユーザー登録後にウェルカムメール送信ジョブをキューへ投入する例です。
<?php
use App\Jobs\SendWelcomeMail;
use App\Models\User;
Route::post('/register', function () {
$user = User::create([
'name' => request('name'),
'email' => request('email'),
'password' => bcrypt(request('password')),
]);
// キューへジョブを投入
dispatch(new SendWelcomeMail($user));
return response()->json(['message' => 'Registered'], 201);
});
ジョブ側(ざっくり):
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
class SendWelcomeMail implements ShouldQueue
{
use Queueable, InteractsWithQueue, SerializesModels;
public function __construct(private User $user)
{
}
public function handle(): void
{
// 実際のメール送信処理
Mail::to($this->user->email)->send(/* ... */);
}
}
実務例:重いレポート生成を非同期化
レポート生成とS3保存のような重い処理を、キューに逃がす例です。
<?php
use App\Jobs\GenerateSalesReport;
use Illuminate\Http\Request;
Route::post('/reports/sales', function (Request $request) {
$year = (int) $request->input('year');
// 処理は非同期。レスポンスはすぐ返す
dispatch(new GenerateSalesReport($year))
->onQueue('reports') // 専用キュー
->delay(now()->addMinutes(1)); // 少し遅延させる
return response()->json([
'message' => 'レポート生成を受け付けました。',
]);
});
ジョブ側では handle() 内で DB 集計 → CSV 生成 → S3 保存などを行い、完了後に通知を送るようにします。
よくある落とし穴・注意
- 非同期になっていない
.envのQUEUE_CONNECTION=syncのままだと、その場でhandle()が実行されます。- 本番で非同期化したい場合は、
databaseやredisなどの接続を設定し、queue:workを常駐させます。
ShouldQueueを付け忘れる- ジョブクラスが
ShouldQueueを実装していないと、「ジョブ」ではなく「コマンド」としてその場で実行されます。
- ジョブクラスが
- ワーカーを動かしていない
php artisan queue:work(または supervisor 等)が動いていないと、いくらdispatch()しても処理されません。
- シリアライズできないプロパティ
- クロージャや外部リソース(PDO、ストリーム)をプロパティに持つと、
Serialization of 'Closure' is not allowedなどのエラーに繋がります。 - 原則として、IDなど最小限の値だけをジョブに渡し、
handle()内で再取得するのが安全です。
- クロージャや外部リソース(PDO、ストリーム)をプロパティに持つと、
代替・関連APIとの比較
- ジョブクラスの
::dispatch()- 例:
SendWelcomeMail::dispatch($user); - 実質的に
dispatch(new SendWelcomeMail($user))と同じ。 - 「どのクラスのジョブか」が明確なので、実務ではこちらがよく使われます。
- 例:
Bus::dispatch()- 例:
Bus::dispatch(new SendWelcomeMail($user)); - Facade ベースで書きたい時や、バッチ/チェーンと合わせて使う場合に選択。
- 例:
dispatch_sync()/dispatch_now()- 強制的に「今すぐ実行」したいときに使用(テストや緊急用途)。
- 非同期前提なら、通常は
dispatch()を使い、同期はキュー接続をsyncにするほうが設計としてはわかりやすいです。
- イベントの
event()event()はイベントリスナを起動する API で、ジョブキューとは別物。- 「時間のかかる処理をバックグラウンドに逃がす」目的なら
dispatch()、
「状態変化に応じて複数の処理をトリガーしたい」ならevent()という使い分けが基本です。
テスト例(Pest)
dispatch() がジョブをキューへ投入しているかを確認する最小テストです。
<?php
use App\Jobs\SendWelcomeMail;
use App\Models\User;
use Illuminate\Support\Facades\Queue;
it('dispatches welcome mail job', function () {
Queue::fake();
$user = User::factory()->create();
dispatch(new SendWelcomeMail($user));
Queue::assertPushed(SendWelcomeMail::class, function ($job) use ($user) {
return $job->user->is($user);
});
});
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
| ジョブがいつまで経っても実行されない | QUEUE_CONNECTION がキュー向けに設定されていても、php artisan queue:work が動いていない | キュー接続を確認し、本番では supervisor などで queue:work を常駐させる |
| 実際には同期処理になっていた | .env が QUEUE_CONNECTION=sync のまま | 非同期化したい環境では database や redis など適切なドライバへ変更 |
Serialization of 'Closure' is not allowed | ジョブのプロパティにクロージャやシリアライズ不可なオブジェクトを持たせている | プロパティには ID やスカラ値、Eloquent モデル程度に留め、handle() 内で必要なオブジェクトを再生成する |
InvalidArgumentException: No connector for [] などキュードライバ関連の例外 | config/queue.php の設定ミス、または .env の QUEUE_CONNECTION が存在しない接続名 | 設定ファイルの connections 配列に対象接続が定義されているか確認し、キャッシュを php artisan config:clear でクリア |

