所有支持的模型事件
在 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);
...
}