laravel 模型事件监听
所有支持的模型事件
在 Eloquent 模型类上进行查询、插入、更新、删除操作时,会触发相应的模型事件(关于事件我们后面会单独讲),不管你有没有监听它们。这些事件包括:
- retrieved:获取到模型实例后触发
- creating:插入到数据库前触发
- created:插入到数据库后触发
- updating:更新到数据库前触发
- updated:更新到数据库后触发
- saving:保存到数据库前触发(插入/更新之前,无论插入还是更新都会触发)
- saved:保存到数据库后触发(插入/更新之后,无论插入还是更新都会触发)
- deleting:从数据库删除记录前触发
- deleted:从数据库删除记录后触发
- restoring:恢复软删除记录前触发
- restored:恢复软删除记录后触发
注:批量更新时不会触发相应事件,因为是直接走查询构建器完成的,绕过了模型方法。
通过订阅者监听模型事件
如果要通过自定义监听器监听模型事件,需要先创建对应的事件类,然后将 Eloquent 支持的模型事件与自定义的事件类建立映射关系,最后将事件类注册到监听器类中,从而完成模型事件监听闭环。
所以,我们先来创建自定义的事件类,这里我们以删除模型为例进行演示,分别定义一个删除前事件类和删除后事件类。我们通过 Artisan 命令来完成事件类初始化:
php artisan make:event UserDeleting
php artisan make:event UserDeleted
然后在这两个事件类中都添加 $user 属性并在构造函数中传入:
// 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
这样,当我们触发 deleting 和 deleted 事件时,底层会将其转化为触发 UserDeleting 和 UserDeleted 事件。
最后,我们还要监听上述自定义的事件类,我们可以通过在 EventServiceProvider 的 listen 属性中为每个事件绑定对应的监听器类,但是学院君更喜欢通过为某个模型类创建一个事件订阅者类来统一处理该模型中的所有事件。在 app/Listeners 目录下创建一个 UserEventSubscriber.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('用户已经删除[' . $event->user->id . ']:' . $event->user->name);
* 为订阅者注册监听器
* @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
通过观察者监听模型事件
针对模型事件这种特殊的事件类型,Laravel 还为我们提供了观察者类来处理模型事件的监听。观察者可以看作是上述订阅者处理模型事件的简化版本,我们不需要自定义事件类,不需要建立映射关系,只需要在观察者类中将需要监听的事件定义为同名方法,并在相应方法中编写业务处理代码即可。当某个模型事件触发时,Eloquent 底层会去该模型上注册的观察者类中通过反射查找是否定义了对应的方法,如果定义了则执行相应的逻辑,否则忽略。
下面我们以 saving 和 saved 事件为例演示如何通过观察者监听模型事件。
首先,我们通过 Artisan 命令初始化针对 User 模型的观察者
php artisan make:observer UserObserver --model=User
默认生成的 UserObserver 会为 created、 updated、deleted、restored、forceDeleted(强制删除) 事件定义一个空方法:
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)
namespace App\Observers;
use App\User;
use Illuminate\Support\Facades\Log;
class UserObserver
public function saving(User $user)
Log::info('即将保存用户到数据库[' . $user->id . ']' . $user->name);
public function creating(User $user)
Log::info('即将插入用户到数据库[' . $user->id . ']' . $user->name);
public function updating(User $user)
Log::info('即将更新用户到数据库[' . $user->id . ']' . $user->name);
public function updated(User $user)
Log::info('已经更新用户到数据库[' . $user->id . ']' . $user->name);
public function created(User $user)
Log::info('已经插入用户到数据库[' . $user->id . ']' . $user->name);
public function saved(User $user)
Log::info('已经保存用户到数据库[' . $user->id . ']' . $user->name);
编写好观察者后,需要将其注册到 User 模型上才能生效,我们可以在 EventServiceProvider 的 boot 方法中完成该工作:
public function boot()
parent::boot();
User::observe(UserObserver::class);