LaravelのEloquentにはObserverという仕組みがあります。ObserverはEloquentのイベント発生によって発火するメソッドの集まりです。
Eloquent:利用の開始 6.0 Laravel#オブザーバ
Observerは次のようにartisanでボイラープレート的なモノを生成できます。
php artisan make:observer UserObserver --model=User
以下の様に生成されたクラスをLaravelの起動時処理で登録することによってイベント監視が動作します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?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を作ると要求を満たせます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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(); } } |
他にもログ取り、検索テーブル用の同期、削除や復元の連鎖など使うと楽になる場面がいくらかあります。また単にモデルのコードが膨れ上がらないための分割としても使えます。