イベントとは
Laravelのイベントシステムは、シンプルなオブザーバーパターンの実装です。 アプリケーション内で起きた出来事(イベント)を発火し、それに反応するリスナーを定義することで、コンポーネント間の依存を最小限に抑えられます。 たとえば「注文が確定した」というイベントを発火すると、「確認メールを送る」「在庫を減らす」「Slackに通知する」といった複数のリスナーがそれぞれ独立して動きます。 注文処理のコードはメール送信やSlack通知の実装を一切知る必要がありません。イベントクラスは
app/Events ディレクトリに、リスナークラスは app/Listeners ディレクトリに置きます。
どちらも存在しない場合は Artisan コマンドが自動で作成します。イベントとリスナーの生成
make:event と make:listener Artisan コマンドでクラスのひな型を生成します。
イベントの登録
イベントディスカバリー(自動検出)
デフォルトでは、Laravel はapp/Listeners ディレクトリをスキャンしてリスナーを自動登録します。
handle または __invoke という名前のメソッドの引数型からイベントとのマッピングを推論します。
bootstrap/app.php で追加スキャン先を指定します。
手動登録
AppServiceProvider の boot メソッドで Event ファサードを使って手動登録することもできます。
イベントの定義
イベントクラスはデータの入れ物です。ロジックは持たず、イベントに関連する情報をプロパティとして保持します。SerializesModels トレイトにより、キューイングされたリスナーがイベントをシリアライズする際に Eloquent モデルが正しく扱われます。
イベントの発火
dispatch スタティックメソッドまたは event() ヘルパーでイベントを発火します。
データベーストランザクション後に発火する
イベントをトランザクションのコミット後にだけ発火したい場合は、ShouldDispatchAfterCommit インターフェースをイベントクラスに実装します。
トランザクションが失敗するとイベントは破棄されます。
リスナーの実装
リスナーはhandle メソッドでイベントを受け取ります。
コンストラクタでは、サービスコンテナが依存を自動注入します。
handle メソッドで false を返すと、後続のリスナーへのイベント伝播を止められます。
キューイングされたリスナー
メール送信や HTTP リクエストなど時間のかかる処理は、キューイングされたリスナーとして非同期に実行できます。ShouldQueue インターフェースを実装するだけで、イベント発火時にリスナーが自動的にキューに積まれます。
キューイングされたリスナーを使う前に、キューの設定とワーカーの起動が必要です。
詳しくはキューとジョブのページを参照してください。
キューの接続・名前・遅延時間をカスタマイズする
PHP アトリビュートを使って接続先・キュー名・遅延時間を設定できます。最大試行回数とタイムアウト
#[Tries] と #[Timeout] アトリビュートで失敗時の挙動を制御できます。
失敗時の処理
failed メソッドを定義すると、リスナーが最大試行回数を超えて失敗したときの後処理を記述できます。
イベントサブスクライバー
イベントサブスクライバーを使うと、関連する複数のイベントハンドラーを一つのクラスにまとめられます。サブスクライバーの作成
subscribe メソッドでイベントとハンドラーのマッピングを配列で返します。
サブスクライバーの登録
イベントディスカバリーが有効な場合、subscribe メソッドから配列を返すサブスクライバーは自動登録されます。
手動で登録する場合は AppServiceProvider の boot メソッドで Event::subscribe を呼び出します。
実践例: ユーザー登録時にウェルカムメールを送信する
1
イベントクラスを作成する
app/Events/UserRegistered.php を編集して登録ユーザーを保持するプロパティを追加します。2
リスナークラスを作成する
ShouldQueue を実装します。3
コントローラでイベントを発火する
ユーザー登録処理の後に
UserRegistered::dispatch() を呼び出します。RegisterController は UserRegistered イベントを発火するだけで、メール送信の実装を知りません。
将来「登録時にSlack通知も送る」となっても、コントローラには何も変更が不要です。4
ワーカーを起動する
キューイングされたリスナーを処理するため、ワーカーを起動します。