在 Eloquent 模型类上进行查询、插入、更新、删除操做时,会触发相应的模型事件,无论你有没有监听它们。这些事件包括:php
retrieved | 获取到模型实例后触发 |
creating | 插入到数据库前触发 |
created | 插入到数据库后触发 |
updating | 更新到数据库前触发 |
updated | 更新到数据库后触发 |
saving | 保存到数据库前触发(插入/更新以前,不管插入仍是更新都会触发) |
saved | 保存到数据库后触发(插入/更新以后,不管插入仍是更新都会触发) |
deleting | 从数据库删除记录前触发 |
deleted | 从数据库删除记录后触发 |
restoring | 恢复软删除记录前触发 |
restored | 恢复软删除记录后触发 |
注:批量更新时不会触发相应事件,由于是直接走查询构建器完成的,绕过了模型方法。laravel
经过监听这些事件,咱们能够在 Eloquent 模型实例生命周期的特定阶段执行特定操做。在 Laravel 中咱们有多种方式来监听模型事件。数据库
经过在模型类上调用要监听事件对应的静态方法,通常咱们会在某个服务提供者的 boot
方法中完成这项工做,好比 EventServiceProvider
。举个例子,假设咱们要监听每次获取模型实例的事件并在日志中记录查询到的用户信息,能够这么作:闭包
// app/Providers/EventServiceProvider.php public function boot() { parent::boot(); // 监听模型获取事件 User::retrieved(function ($user) { Log::info('从模型中获取用户[' . $user->id . ']:' . $user->name); }); }
上面这段代码中表示咱们在 User
模型上监听 retrieved
事件,而后经过一个闭包函数执行对应的处理逻辑,该闭包函数传入参数是模型实例,在处理逻辑中,咱们经过 Log
门面记录日志信息。app
以删除模型为例进行演示,分别定义一个删除前事件类和删除后事件类。咱们经过 Artisan 命令来完成事件类初始化:ide
php artisan make:event UserDeleting php artisan make:event UserDeleted
而后在这两个事件类中都添加 $user
属性并在构造函数中传入:函数
// app/Events/UserDeleted.php // app/Events/UserDeleting.php public $user; public function __construct(User $user) { $this->user = $user; }
在 User
模型类中创建模型事件与自定义事件类的映射,这能够经过 $dispatchesEvents
属性来完成:this
//创建模型事件与自定义事件类的映射 protected $dispatchesEvents = [ 'deleting' => UserDeleting::class, 'deleted' => UserDeleted::class ];
这样,当咱们触发 deleting
和 deleted
事件时,底层会将其转化为触发 UserDeleting
和 UserDeleted
事件。spa
咱们还要监听上述自定义的事件类,咱们能够经过在 EventServiceProvider
的 listen
属性中为每一个事件绑定对应的监听器类,也能够经过为某个模型类建立一个事件订阅者类来统一处理该模型中的全部事件。在 app/Listeners
目录下建立一个 UserEventSubscriber.php
文件做为订阅者类,编写代码以下rest
<?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
事件为例演示如何经过观察者监听模型事件。
User
模型的观察者laravel5.7以上能够使用如下命令进行建立观察者,laravel5.7如下须要手动建立
php artisan make:observer UserObserver --model=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) { // } }
能够把前面定义的 retrived
、deleting
、deleted
事件监听代码迁移过来,也能够将不需监听的事件方法移除,这里咱们将编写保存模型时涉及的模型事件,包括 saving
、creating
、updating
、updated
、created
、saved
<?php namespace App\Observers; use App\Model\User; use 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模型的观察者 User::observe(UserObserver::class); }
关于三种监听 Eloquent 模型事件的方式,如何选择,视状况而定。若是只是监听一两个模型事件,第一种方式比较合适;若是仅仅监听系统支持的模型事件,而且要监听多个模型的多个事件,观察者是最佳选择;若是还要在模型类上监听更多系统模型事件以外的自定义事件,则使用订阅者来监听比较合适。