Laravel 中模型事件 Observer 的使用

zhonglang發表於2022-05-24

如果想監聽 model 中的各種事件,諸如updatedcreateddeleted 等模型事件,你可以使用 Observer 類進行統一管理。只需這一個類,你就可以監聽上述多種模型事件,十分地方便。

舉一個例子,假如你想監聽 User 模型的變化。你可以使用以下命令建立 User 模型的觀察者:

php artisan make:observer UserObserver --model=User

你會得到如下的檔案:

<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
    /**
     * Handle the User "created" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function created(User $user)
    {
        //
    }

    /**
     * Handle the User "updated" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function updated(User $user)
    {
        //
    }

    /**
     * Handle the User "deleted" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function deleted(User $user)
    {
        //
    }

    /**
     * Handle the User "restored" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function restored(User $user)
    {
        //
    }

    /**
     * Handle the User "force deleted" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function forceDeleted(User $user)
    {
        //
    }
}

然後,在 app/Providers/EventServiceProvider.php 中註冊:

use App\Models\User;
use App\Observers\UserObserver;

/**
 * Register any events for your application.
 *
 * @return void
 */
public function boot()
{
    User::observe(UserObserver::class);
}

或者,你也可以在 app/Providers/AppServiceProvider.php 中註冊:

use App\Models\User;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    User::observe(UserObserver::class);
}

⚠️ 注意:不能在兩個地方同時註冊,否則會觸發重複的動作。

  1. 使用正確的獲取模型方法,以便更好的監聽 update 事件。

        // wrong
        User::query()->where('id', $id)->update();
    
        // suggest
        User::find($id)->update();
        // or
        $user = User::find($id);
        $user->update();
  1. 監聽某些欄位的更新。

    /**
     * Handle the Seek "updated" event.
     *
     * @param User $user
     * @return void
     */
    public function updated(User $user)
    {
        if ($user->wasChanged('status')) {
            // to do something
        }
    }
    
    

上面使用到了 wasChanged() 方法,該方法是儲存之後執行,檢視監聽的模型屬性是否被修改。此外,還有 isDirty() 方法,該方法是在儲存之前執行,作用同上。

上述程式碼例項 updated 方法中,監聽的是更新執行後的資料變化, 應使用 wasChanged() 方法獲取指定欄位的變化,或者使用 getChanges() 方法,獲取所有變化的欄位。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
堅定地後端開發者

相關文章