有遇到这个bug吗?withoutEvents函数里面的事件被触发

描述:

Version: Laravel Framework 7.26.1
在调用withoutEvents() 后,Model中的保存事件仍然被触发。

安装项目

composer create-project –prefer-dist laravel/laravel blog

创建一个Model

<?php

namespace App;
use App\Events\UserSavedEvent;
use Illuminate\Database\Eloquent\Model;

class TestModel extends Model
{
    public $table = 'users';

    protected $dispatchesEvents = [
        'saved' => UserSavedEvent::class,
    ];
}

创建Event

<?php

namespace App\Events;

use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class UserSavedEvent
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct()
    {
        dd('UserSavedEvent');
    }

}

测试用例

Route::get('/', function () {
    TestModel::withoutEvents(function () {
        $user = TestModel::first();
        $user->save();
    });
    return view('welcome');
});

结果

withoutEvents中的saved事件被触发;

withoutEvents函数里面的事件被触发

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

刚看了一遍文档,你使用的这种 event 是需要 listener 配合的,事件的逻辑在 listener 里面,无论事件是否执行,event 的构造函数总会执行。我觉得使用 observer 的方式会更简单一些。

3年前 评论
PhoenixIcy 3年前
Yoger (楼主) 3年前
Yoger (楼主) 3年前
Yoger (楼主) 3年前
天意 (作者) 3年前
Yoger (楼主) 3年前
天意 (作者) 3年前
天意 (作者) 3年前
Yoger (楼主) 3年前
天意 (作者) 3年前

@Yoger

我看了下源码,最终事件执行是在 vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php 文件的 206 行执行的。

    protected function fireCustomModelEvent($event, $method)
    {
        if (! isset($this->dispatchesEvents[$event])) {
            return;
        }

        $result = static::$dispatcher->$method(new $this->dispatchesEvents[$event]($this));  // 这一行

        if (! is_null($result)) {
            return $result;
        }
    }

可以看到 new $this->dispatchesEvents[$event]($this) 这里是直接 new 了一下,所以构造函数执行了。

事件是否会真正执行,要看 static::$dispatcher,而 withoutEvents 做的事情就是把 dispatcher 设置为 NullDispatcherNullDispatcher 里面的函数体是空的。不会执行事件 listener。

我这里是 6.18.25 版本。我去 github 上面看了一下 ,早在 5.5 版本,还没有 withoutEvents 函数的时候 ,事件就已经这这样的了。会直接 new 一下事件。下面是 5.5 版本的代码链接:

github.com/laravel/framework/blob/...

3年前 评论
Yoger (楼主) 3年前
Yoger (楼主) 3年前
天意 (作者) 3年前
天意 (作者) 3年前
Yoger (楼主) 3年前
天意 (作者) 3年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!