laravel Eloquent 模型事件和监听方式

本文详细介绍了在 Laravel 框架中如何使用 Eloquent ORM 的模型事件,包括检索、创建、更新、删除等操作触发的不同事件,以及如何通过静态方法、订阅者和观察者三种方式来监听和处理这些事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在 Eloquent 模型类上进行查询、插入、更新、删除操作时,会触发相应的模型事件,不管你有没有监听它们。

这些事件包括:

retrieved:获取到模型实例后触发 creating:插入到数据库前触发 created:插入到数据库后触发
updating:更新到数据库前触发 updated:更新到数据库后触发
saving:保存到数据库前触发(插入/更新之前,无论插入还是更新都会触发)
saved:保存到数据库后触发(插入/更新之后,无论插入还是更新都会触发)
deleting:从数据库删除记录前触发
deleted:从数据库删除记录后触发
restoring:恢复软删除记录前触发
restored:恢复软删除记录后触发

注:批量更新时不会触发相应事件,因为是直接走查询构建器完成的,绕过了模型方法。

通过静态方法监听模型事件

在模型类上调用要监听事件对应的静态方法

// app/Providers/EventServiceProvider.php

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

    // 监听模型获取事件,闭包函数传入参数-模型实例
    User::retrieved(function ($user) {
        Log::info('从模型中获取用户[' . $user->id . ']:' . $user->name);
    });
}

通过订阅者监听模型事件

操作:
1.创建对应的事件类

php artisan make:event UserDeleted

2.将 Eloquent 支持的模型事件与自定义的事件类建立映射关系

# app/Models/User.php
protected $dispatchesEvents = [
    'deleting' => UserDeleting::class,
    'deleted' => UserDeleted::class
];

3.将事件类注册到监听器类中
第1种方式:
listen属性中为每个事件,绑定对应监听器 (有event, 有listener)

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'App\Events\Event' => [
            'App\Listeners\EventListener',
            'App\Listeners\UserDeletingListener',
            'App\Listeners\UserDeletedListener',
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        //
        Sheet::observe(SheetObserver::class);
    }
}

第2种方式:
为某个模型类创建一个事件订阅者类来统一处理该模型中的所有事件

<?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'
        );
    }
}
// app/Providers/EventServiceProvider.php

protected $subscribe = [
    UserEventSubscriber::class
];

触发代码:

$user = User::findOrFail(10);
$user->delete();

[2018-12-05 02:14:50] local.INFO: 从模型中获取用户[10]:Dr. Kory Abshire IV
[2018-12-05 02:14:50] local.INFO: 用户即将删除[10]:Dr. Kory Abshire IV
[2018-12-05 02:14:50] local.INFO: 用户已经删除[10]:Dr. Kory Abshire IV

通过观察者监听模型事件

观察者/订阅者区别:

订阅者处理模型事件的简化版本
不需要自定义事件类
不需要建立映射关系
只需要在观察者类中将需要监听的事件定义为同名方法,处理业务逻辑即可

创建User模型的观察者

php artisan make:observer UserObserver --model=User

默认生成的 UserObserver 会为 created、 updated、deleted、restored、forceDeleted(强制删除) 事件定义一个空方法

对于监听的事件方法,可以根据需要自行增删

<?php

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.php
public function boot()
{
    parent::boot();
    
    User::observe(UserObserver::class);
    
    ...
}

触发事件

$user = new User();
$user->name = '学院君测试号01';
$user->email = 'test01@laravelacademy.org';
$user->password = bcrypt('secret');
$user->save();

[2018-12-05 02:50:00] local.INFO: 即将保存用户到数据库[]学院君测试号01
[2018-12-05 02:50:00] local.INFO: 即将插入用户到数据库[]学院君测试号01
[2018-12-05 02:50:00] local.INFO: 已经插入用户到数据库[19]学院君测试号01
[2018-12-05 02:50:00] local.INFO: 已经保存用户到数据库[19]学院君测试号01

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值