LoginSignup
74
67

More than 5 years have passed since last update.

Laravelのeloquentのeventでcreated_byとかupdated_byとか更新するobserverとtrait

Last updated at Posted at 2017-04-02

Eloquentには、creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored といった、新規作成する時、、、、みたいなイベントをフックすることができるような仕組みがあるのだが、
https://laravel.com/docs/5.3/eloquent#events

ログインしてるユーザーの操作を保存したいのだけど、ググってもイマイチいいのがなかったので考えました。

ググって微妙だったやつ

全部のモデルにbootのfunctionを新しく足して、イベント全部書き連ねるのとかだるい

ちょっと良くなってるけど、bootのfunction書きたくない

このモデル何設定されてんだっけ、ってのmodelの中で見たいけどservice providerのbootにあるとかなんか変。

ってのがあったんだけど、上記の理由により、bootに書きたくない、observerは使いたい、でもservice providerには書きたくない、ならば、modelにtraitが良いかなと思って書きました。

Observerクラス

作成前、などのイベントで、ログイン済みのuserのidを設定するobserverを書く。
ログイン済みのユーザーIDを各フィールドにマッピングする。
xxxingのイベントは、sql文発行する前。

app/Observers/AuthorObserver.php
<?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を呼んでくれるようです。
他と競合しないようにするってやっぱ重要ですね素敵。

app/Traits/AuthorObservable.php
<?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とか書かなくていいの。モデルが綺麗なまま。

app/Models/CheckIn.php
<?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::って書くの正しいんだろうか?なんか不安。

74
67
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
74
67