laravel 模型事件監(jiān)聽

所有支持的模型事件
在 Eloquent 模型類上進行查詢、插入、更新、刪除操作時,會觸發(fā)相應的模型事件(關(guān)于事件我們后面會單獨講),不管你有沒有監(jiān)聽它們。這些事件包括:

- retrieved:獲取到模型實例后觸發(fā)
- creating:插入到數(shù)據(jù)庫前觸發(fā)
- created:插入到數(shù)據(jù)庫后觸發(fā)
- updating:更新到數(shù)據(jù)庫前觸發(fā)
- updated:更新到數(shù)據(jù)庫后觸發(fā)
- saving:保存到數(shù)據(jù)庫前觸發(fā)(插入/更新之前,無論插入還是更新都會觸發(fā))
- saved:保存到數(shù)據(jù)庫后觸發(fā)(插入/更新之后,無論插入還是更新都會觸發(fā))
- deleting:從數(shù)據(jù)庫刪除記錄前觸發(fā)
- deleted:從數(shù)據(jù)庫刪除記錄后觸發(fā)
- restoring:恢復軟刪除記錄前觸發(fā)
- restored:恢復軟刪除記錄后觸發(fā)

注:批量更新時不會觸發(fā)相應事件,因為是直接走查詢構(gòu)建器完成的,繞過了模型方法。


通過訂閱者監(jiān)聽模型事件
如果要通過自定義監(jiān)聽器監(jiān)聽模型事件,需要先創(chuàng)建對應的事件類,然后將 Eloquent 支持的模型事件與自定義的事件類建立映射關(guān)系,最后將事件類注冊到監(jiān)聽器類中,從而完成模型事件監(jiān)聽閉環(huán)。

所以,我們先來創(chuàng)建自定義的事件類,這里我們以刪除模型為例進行演示,分別定義一個刪除前事件類和刪除后事件類。我們通過 Artisan 命令來完成事件類初始化:

php artisan make:event UserDeleting
php artisan make:event UserDeleted

然后在這兩個事件類中都添加 $user 屬性并在構(gòu)造函數(shù)中傳入:

// app/Events/UserDeleted.php
// app/Events/UserDeleting.php

public $user;

/**
 * Create a new event instance.
 *
 * @return void
 */
public function __construct(User $user)
{
    $this->user = $user;
}

在 User 模型類中建立模型事件與自定義事件類的映射,這可以通過 $dispatchesEvents 屬性來完成:

protected $dispatchesEvents = [
    'deleting' => UserDeleting::class,
    'deleted' => UserDeleted::class
];

這樣,當我們觸發(fā) deleting 和 deleted 事件時,底層會將其轉(zhuǎn)化為觸發(fā) UserDeleting 和 UserDeleted 事件。

最后,我們還要監(jiān)聽上述自定義的事件類,我們可以通過在 EventServiceProvider 的 listen 屬性中為每個事件綁定對應的監(jiān)聽器類,但是學院君更喜歡通過為某個模型類創(chuàng)建一個事件訂閱者類來統(tǒng)一處理該模型中的所有事件。在 app/Listeners 目錄下創(chuàng)建一個 UserEventSubscriber.php 文件作為訂閱者類,編寫代碼如下

?php

namespace App\Listeners;

use App\Events\UserDeleted;
use App\Events\UserDeleting;
use Illuminate\Support\Facades\Log;

class UserEventSubscriber
{
    /**
     * 處理用戶刪除前事件
     */
    public function onUserDeleting($event) {
        Log::info('用戶即將刪除[' . $event->user->id . ']:' . $event->user->name);
    }

    /**
     * 處理用戶刪除后事件
     */
    public function onUserDeleted($event) {
        Log::info('用戶已經(jīng)刪除[' . $event->user->id . ']:' . $event->user->name);
    }

    /**
     * 為訂閱者注冊監(jiān)聽器
     *
     * @param  Illuminate\Events\Dispatcher  $events
     */
    public function subscribe($events)
    {
        $events->listen(
            UserDeleting::class,
            UserEventSubscriber::class . '@onUserDeleting'
        );

        $events->listen(
            UserDeleted::class,
            UserEventSubscriber::class . '@onUserDeleted'
        );
    }
}

最后,我們在 EventServiceProvider 中注冊這個訂閱者,使其生效:

// app/Providers/EventServiceProvider.php

protected $subscribe = [
    UserEventSubscriber::class
];

通過觀察者監(jiān)聽模型事件
針對模型事件這種特殊的事件類型,Laravel 還為我們提供了觀察者類來處理模型事件的監(jiān)聽。觀察者可以看作是上述訂閱者處理模型事件的簡化版本,我們不需要自定義事件類,不需要建立映射關(guān)系,只需要在觀察者類中將需要監(jiān)聽的事件定義為同名方法,并在相應方法中編寫業(yè)務處理代碼即可。當某個模型事件觸發(fā)時,Eloquent 底層會去該模型上注冊的觀察者類中通過反射查找是否定義了對應的方法,如果定義了則執(zhí)行相應的邏輯,否則忽略。

下面我們以 saving 和 saved 事件為例演示如何通過觀察者監(jiān)聽模型事件。

首先,我們通過 Artisan 命令初始化針對 User 模型的觀察者

php artisan make:observer UserObserver --model=User

默認生成的 UserObserver 會為 created、 updated、deleted、restored、forceDeleted(強制刪除) 事件定義一個空方法:

<?php

namespace App\Observers;

use App\User;

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

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

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

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

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

寫入邏輯

<?php

namespace App\Observers;

use App\User;
use Illuminate\Support\Facades\Log;

class UserObserver
{
    public function saving(User $user)
    {
        Log::info('即將保存用戶到數(shù)據(jù)庫[' . $user->id . ']' . $user->name);
    }

    public function creating(User $user)
    {
        Log::info('即將插入用戶到數(shù)據(jù)庫[' . $user->id . ']' . $user->name);
    }

    public function updating(User $user)
    {
        Log::info('即將更新用戶到數(shù)據(jù)庫[' . $user->id . ']' . $user->name);
    }

    public function updated(User $user)
    {
        Log::info('已經(jīng)更新用戶到數(shù)據(jù)庫[' . $user->id . ']' . $user->name);
    }

    public function created(User $user)
    {
        Log::info('已經(jīng)插入用戶到數(shù)據(jù)庫[' . $user->id . ']' . $user->name);
    }

    public function saved(User $user)
    {
        Log::info('已經(jīng)保存用戶到數(shù)據(jù)庫[' . $user->id . ']' . $user->name);
    }
}

編寫好觀察者后,需要將其注冊到 User 模型上才能生效,我們可以在 EventServiceProvider 的 boot 方法中完成該工作:

public function boot()
{
    parent::boot();

    User::observe(UserObserver::class);

    ...
}

轉(zhuǎn)自https://laravelacademy.org/post/9713.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • Laravel框架一:原理機制篇 Laravel作為在國內(nèi)國外都頗為流行的PHP框架,風格優(yōu)雅,其擁有自己的一些特...
    Mr_Z_Heng閱讀 3,933評論 0 13
  • Laravel 學習交流 QQ 群:375462817 本文檔前言Laravel 文檔寫的很好,只是新手看起來會有...
    Leonzai閱讀 8,706評論 2 12
  • 事件 簡介 laravel 的事件提供了一種簡單的觀察者實現(xiàn)。它允許你在應用中進行訂閱和監(jiān)聽事件。事件類通常都是存...
    Dearmadman閱讀 3,647評論 0 3
  • Laravel 模型事件允許你監(jiān)聽模型生命周期內(nèi)的多個關(guān)鍵點,甚至可以在阻止一個模型的保存或者刪除。 Larave...
    summerbluet閱讀 1,337評論 0 4
  • 安裝模塊如不指定版本號 默認會安裝最新的版本 這個命令會在當前目錄生成一個package.json文件,這個文件中...
    Cola丶ZYQ閱讀 1,323評論 0 2

友情鏈接更多精彩內(nèi)容