LaravelのEloquentにはObserverという仕組みがあります。ObserverはEloquentのイベント発生によって発火するメソッドの集まりです。
Eloquent:利用の開始 6.0 Laravel#オブザーバ
Observerは次のようにartisanでボイラープレート的なモノを生成できます。
php artisan make:observer UserObserver --model=User
以下の様に生成されたクラスをLaravelの起動時処理で登録することによってイベント監視が動作します。
<?php namespace App\Providers; use App\Observers\UserObserver; use App\User; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { //省略 /** * 全アプリケーションサービスの初期起動 * * @return void */ public function boot() { User::observe(UserObserver::class); // ここでモデル::observe(オブザーバクラス::class)が基本 Post::observe([PostObserver::class, BBSObserver::class); // 複数でもOK foreach (['Post', 'Comment'] as $className) {// 共通のオブザーバを使うならこんな書き方もあり /* @var Eloquent $className */ $className::observe(UpdateTalkedAtObserver::class); } } }
オブザーバの使い時は色々あります。例えば、ある集約全体における更新日時を記録する場合です。
LaravelのEloquentにはタイムスタンプを自動記録する機能があり、あるレコードを更新した際にそのレコード内の特定のカラム(デフォはupdated_at)に日時を記録してくれます。これだけでも便利なのですが、これだけではシステムの要求を満たせない場合もあります。例えば、あるユーザの情報が複数テーブルに分割されており、いずれかの情報が更新された時にユーザ情報が更新されたとし、その更新日時を記録する必要がある、という場合です。より具体的に次のER図のテーブル構成があるとします。
ブログへの投稿かコメントを行った時にユーザの最終発言日時を記録する、とします。このような時、次のObserverを作ると要求を満たせます。
class UpdateTalkedAtObserver { public function created(Eloquent $postOrComment) // 宣言した型に依らず、登録したEloquentクラスのインスタンスが渡される { $postOrComment->user->talked_at = $postOrComment->created_at; $postOrComment->user->save(); } public function updated(Eloquent $postOrComment) // 宣言した型に依らず、登録したEloquentクラスのインスタンスが渡される { $postOrComment->user->talked_at = $postOrComment->updated_at; $postOrComment->user->save(); } }
他にもログ取り、検索テーブル用の同期、削除や復元の連鎖など使うと楽になる場面がいくらかあります。また単にモデルのコードが膨れ上がらないための分割としても使えます。