Eloquentには、creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored といった、新規作成する時、、、、みたいなイベントをフックすることができるような仕組みがあるのだが、
https://laravel.com/docs/5.3/eloquent#events
ログインしてるユーザーの操作を保存したいのだけど、ググってもイマイチいいのがなかったので考えました。
ググって微妙だったやつ
- イベントをフックするのは、各モデルのbootに、こんな感じでhookを書けば、、、とか、
https://laracasts.com/discuss/channels/general-discussion/where-should-i-set-a-created-by-to-the-users-id
全部のモデルにbootのfunctionを新しく足して、イベント全部書き連ねるのとかだるい
- オブザーバークラス作って、各モデルのbootに書けば、、、、とか、
https://laracasts.com/discuss/channels/laravel/how-to-automaticly-update-updated-by-created-by-fields-using-eloquent
ちょっと良くなってるけど、bootのfunction書きたくない
- 公式では、Observerクラスを書いてサービスプロバイダのbootでモデルごとにobserveを書いとけば、、、、とか
https://laravel.com/docs/5.3/eloquent#events
このモデル何設定されてんだっけ、ってのmodelの中で見たいけどservice providerのbootにあるとかなんか変。
ってのがあったんだけど、上記の理由により、bootに書きたくない、observerは使いたい、でもservice providerには書きたくない、ならば、modelにtraitが良いかなと思って書きました。
Observerクラス
作成前、などのイベントで、ログイン済みのuserのidを設定するobserverを書く。
ログイン済みのユーザーIDを各フィールドにマッピングする。
xxxingのイベントは、sql文発行する前。
<?php
namespace App\Observers;
use Illuminate\Database\Eloquent\Model;
class AuthorObserver
{
public function creating(Model $model){
$model->created_by = \Auth::user()->id;
}
public function updating(Model $model){
$model->updated_by = \Auth::user()->id;
}
public function saving(Model $model){
$model->updated_by = \Auth::user()->id;
}
public function deleting(Model $model){
$model->deleted_by = \Auth::user()->id;
}
public function restoring(Model $model){
$model->restored_by = \Auth::user()->id;
}
}
restoringはsoftdeleteの時だけしか使われません。
Observerをロードするtrait
boot{トレイトの名前}
ってpublic static function
を作っておくと
\Illuminate\Database\Eloquent\Model::bootTraits
さんが、うまいことbootのあとにtraitのbootを呼んでくれるようです。
他と競合しないようにするってやっぱ重要ですね素敵。
<?php
namespace App\Traits;
use App\Observers\AuthorObserver;
use Illuminate\Database\Eloquent\Model;
trait AuthorObservable
{
public static function bootAuthorObservable()
{
self::observe(AuthorObserver::class);
}
}
Modelでのロード
モデルで、このtraitをuse AuthorObservable;
ってuse
すればいいだけ。
bootとか書かなくていいの。モデルが綺麗なまま。
<?php
namespace App\Models;
use App\Traits\AuthorObservable;
use Illuminate\Database\Eloquent\Model;
/**
* Foursquareみたいに、お店にチェックインしたってのを持つテーブル
*/
class CheckIn extends Model
{
use AuthorObservable;
public function shop()
{
return $this->belongsTo('App\Models\Shop');
}
public function created_by()
{
return $this->belongsTo('App\Models\User', 'created_by');
}
public function updated_by()
{
return $this->belongsTo('App\Models\User', 'updated_by');
}
}
これで、お店へのブックマークとか、レビューとか、そういうものが、同じtraitでまかなえますね。
クラスの名前がダサいので誰かそれっぽい名前をアドバイスいただけると助かります。
あと、traitでself::って書くの正しいんだろうか?なんか不安。