簡單的介紹 Eloquent 模型生命週期

finecho發表於2019-01-23

@這是小豪的第七篇文章

在沒有接觸 Laravel 的時候,都還不知道 PHP 有事件、模型生命週期這一說,一直都是什麼時候需要什麼時候呼叫,程式碼寫的一大坨,哈哈,今天帶大家來看看 Eloquent 模型生命週期到底是什麼樣子的什麼時候使用。

準備

我們以文章為例子:

class Post extends Model
{
    protected $fillable = [
        'user_id', 'title', 'content',
    ];

    protected $casts = [
        'id' => 'int',
        'user_id' => 'int',
    ];

    protected static function boot()
    {
        parent::boot(); // TODO: Change the autogenerated stub

        static::retrieved(function (Post $post) {
            echo 'This is retrieved' . "\n";
        });

        static::creating(function (Post $post) {
            echo 'This is creating' . "\n";
        });

        static::created(function (Post $post) {
            echo 'This is created' . "\n";
        });

        static::updating(function (Post $post) {
            echo 'This is updating' . "\n";
        });

        static::updated(function (Post $post) {
            echo 'This is updated' . "\n";
        });

        static::saving(function (Post $post) {
            echo 'This is saving' . "\n";
        });

        static::saved(function (Post $post) {
            echo 'This is saved' . "\n";
        });

        static::deleting(function (Post $post) {
            echo 'This is deleting' . "\n";
        });

        static::deleted(function (Post $post) {
            echo 'This is deleted' . "\n";
        });
    }
}

建立文章

public function store(Request $request)
{
    $post = Post::create(['title' => '這是文章標題', 'content' => '這是文章內容', 'user_id' => Auth::id()]);

    return \response()->json($post);
}

此時我們可以看到輸出的順序依次為:

1 2 3 4
This is saving This is creating This is created This is saved

更新文章

public function update(Request $request)
{
    $post = Post::find(1);

    $post->title = '這是更新的文章標題';

    $post->save();

    return \response()->json($post);
}

此時我們可以看到輸出的順序依次為:

1 2 3 4 5
This is retrieved This is saving This is updating This is updated This is saved

從簡單的更新與建立中,大家可以看到觸發的事件中多了一個 retrieved ,以及 creatingcreated 依次變為了 updatingupdated,其餘的都是保持一致的。多出來的 retrieved 是從哪裡蹦出來的呢,我們看看文件中給出的解釋:

“當從資料庫檢索現有模型時,會觸發retrieved 事件”

其實我剛才看到這句話的時候有點蒙,啥呀,哈哈。下面簡單給大家再演示一遍看看:

public function test()
{
    $post = Post::find(1);

    // 輸出:This is retrieved

    $post = Post::create(['title' => '這是文章標題 2 ', 'content' => '這是文章內容 2 ', 'user_id' => Auth::id()]);

    // 輸出:.....

    $posts = Post::all();

    // 輸出:This is retrieved、This is retrieved
}

大家有沒有看出啥子端倪,哈哈,一條記錄觸發了一次。

刪除文章

public function destroy(Request $request)
{
    $post = Post::find(1);

    $post->delete();
}

此時我們可以看到輸出的順序依次為:

1 2 3
This is retrieved This is deleting This is deleted

批次更新

public function test(Request $request)
{
    Post::where('id' ,'>' ,0)->update(['title' => '這是文章標題更新', 'content' => '這是文章內容', 'user_id' => 1]);
}

此時我們可以看到沒有輸出,為啥呢?透過 Eloquent 進行批次更新時,不會為更新的模型觸發 saved 和 updated 模型事件。這是因為在進行批次更新時,並未檢索該模型。

批次刪除

public function test(Request $request)
{
    Post::where('id' ,'>' ,0)->delete();
}

也是一樣沒有輸出的噢,哈哈。

結束語

大家可能會問啥時候會用到這些模型事件呢,舉例一些給大家看看:

    protected static function boot()
    {
        parent::boot(); // TODO: Change the autogenerated stub

        static::retrieved(function (Post $post) {
            // 文章加精
            \dispatch(new PostAddPopular($post));
        });

        static::creating(function (Post $post) {
            $post->user_id = Auth::id();
        });

        static::saving(function (Post $post) {
            // 敏感詞過濾
            $post->title = \dispatch_now(new FilterThreadSensitiveWords($post->title));
        });
    }

    ......

等等還有好多妙用,大家可以結合自己的需求對生命週期完美的利用哈哈。

也可以定義一個觀察者進行監聽處理的,不過沒有很大處理量的時候,還是建議這種直接在模型中定義的方式噢。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
finecho # Lhao

相關文章