Laravel Eloquent模型更新事件未被触发。

17

大家圣诞节快乐!

我是 Laravel 的新手。有一个初学者问题,当我试图使用服务提供商和模型事件来记录更新信息时。

我按照在线文档的指导操作:https://laravel.com/docs/5.3/eloquent#events

把所有代码放在一起后,我发现模型事件仅在创建用户时触发,但在编辑用户时从未记录任何内容。

我错过了什么吗?感觉 $user 没有被正确地分配。它来自哪里?来自其他服务提供程序吗?

非常感谢任何解释或提示!

<?php

namespace App\Providers;

use App\User;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        User::creating(function ($user) {
            Log::info('event creating');
        });

        User::created(function ($user) {
            Log::info('event created');
        });

        User::updating(function ($user) {
            Log::info('event updating');
        });

        User::updated(function ($user) {
            Log::info('event updated');
        });

        User::saving(function ($user) {
            Log::info('event saving');
        });

        User::saved(function ($user) {
            Log::info('event saved');
        });

        User::deleting(function ($user) {
            Log::info('event deleting');
        });

        User::deleted(function ($user) {
            Log::info('event deleted');
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

你的创建和编辑代码是什么?可能是因为没有进行任何更改,因此事件没有被触发,或者你正在进行大量更新,而这根本没有触发事件。 - Lionel Chan
感谢@LionelChan,Ohgodwhy和Eric Tucker!在将更新更改为以下内容后,事件触发器完美地工作:User::find($id)->update(['username' => $newUsername]); 感谢你们的帮助! - northblue
同样适用于 delete。只有在创建模型对象时,模型才会触发相关事件。这意味着它只会在你使用 findgetfirst 来检索对象时才会触发 :) - Lionel Chan
2个回答

54
您需要从数据库中检索用户,然后保存该用户以触发事件。例如:

以下操作将不会触发更新事件:


User::where('id', $id)->update(['username' => $newUsername]);

这将触发更新事件:

User::find($id)->update(['username' => $newUsername]);

这个可以工作:User::find(4)->update(['earings' => 0]);,而这个不行:$user = User::find(1); $user->earings=0; $user->update()。在第二种情况下,事件没有被触发。你能解释一下为什么吗?这两个语句有什么区别?它们不都是批量赋值吗? - padawanTony
1
你的两个示例都在做同样的事情,并且只有在模型被修改时才会触发事件。在你的情况下,只有当$user->earings不等于0时,模型事件才会触发。这可能就是你所经历的。 - Eric Tucker
你的意思是如果earings的原始值不是0。确实不是。这就是为什么我要做$user->earings=0;。这样它就会改变,实例也会变得脏。 - padawanTony
1
当Laravel从数据库中提取模型时,它会立即存储原始状态的快照。然后,在将更改持久化到数据库之前,当您更新属性时,Laravel会检查每个属性的当前状态与最初从数据库中提取的状态是否匹配。只有当其中至少一个不匹配时,该模型被视为脏模型,然后才会向数据库发送实际的更新命令并触发事件。 - Eric Tucker
@Grant 这是因为在这种情况下,当模型从数据库中被填充时,每个模型都会注册模型事件。这些不是数据库触发器。如果没有从数据库中提取行,例如:User::where('id', $id)->update(['username' => $newUsername]);,你只是执行了 UPDATE users SET username = ? WHERE id = ?,这样就绕过了那些事件。 - Eric Tucker
显示剩余3条评论

10
可能的原因:
  1. 该行根本没有被更新 - 没有更改。 因此不会触发事件,

  2. 您使用了 update。 在这里查看文档:https://laravel.com/docs/5.3/eloquent#updates

通过 Eloquent 发出批量更新时,已保存和已更新的模型事件不会针对更新的模型触发。 这是因为在发出批量更新时,实际上从未检索到模型。


简而言之,您必须发出 find($id) 并手动修改属性才能使其正常工作。 - Ohgodwhy
这个可以工作:User::find(4)->update(['earings' => 0]);,而这个不行:$user = User::find(1); $user->earings=0; $user->update()。在第二种情况下,事件没有被触发。你能解释一下为什么吗?这两个语句有什么区别?它们不都是批量赋值吗? - padawanTony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接