【问题标题】:Laravel: Check with Observer if Column was Changed on UpdateLaravel:与观察者检查列是否在更新时更改
【发布时间】:2018-07-25 09:13:39
【问题描述】:

我正在使用Observer 来查看用户是否更新。

每当用户是updated 时,我想检查他的email 是否已更改。

这样的事情可能吗?

class UserObserver
{


    /**
     * Listen to the User created event.
     *
     * @param  \App\User  $user
     * @return void
     */
    public function updating(User $user)
    {
      // if($user->hasChangedEmailInThisUpdate()) ?
    }

}

【问题讨论】:

  • 您的意思是isDirty 方法?还有wasChanged
  • @tadman 是的!这就是我要找的。这与观察者兼容吗?我认为更新是在将更改分配给user 之后调用,但在存储之前调用,对吧?
  • 我不能 100% 确定细节,因此您可能需要在这里进行试验。脏跟踪是许多 ORM 的共同特征,包括 Eloquent。

标签: php mysql laravel-5


【解决方案1】:

编辑:感谢https://stackoverflow.com/a/54307753/2311074 getOriginal

正如tadman 在 cmets 中已经说过的,isDirty 方法可以解决问题:

class UserObserver
{


    /**
     * Listen to the User updating event.
     *
     * @param  \App\User  $user
     * @return void
     */
    public function updating(User $user)
    {
      if($user->isDirty('email')){
        // email has changed
        $new_email = $user->email; 
        $old_email = $user->getOriginal('email');
      }
    }

}

如果您想知道isDirtywasChanged 之间的区别,请参阅https://stackoverflow.com/a/49350664/2311074

【讨论】:

  • 非常感谢,这就是我正在搜索的内容。
  • 不需要再次从数据库中传输模型,请参阅我的更新版本的答案
【解决方案2】:

您不必再次从数据库中获取用户。以下应该有效:

public function updating(User $user)
{
  if($user->isDirty('email')){
    // email has changed
    $new_email = $user->email; 
    $old_email = $user->getOriginal('email'); 
  }
}

【讨论】:

  • 我赞成您对已接受答案的评论,但由于它现在是重复的,所以对此表示反对
  • @aowie1 这个答案在我评论后更新了:'(
  • 我赞成您的回答,因为我认为它不值得反对。但是,我认为它的常见做法是编辑对 cme​​ts 答案的微小改进。我猜想使用getOriginal 而不是find 只是一个小改进,因为两者都有效,而答案的主要部分是如何查找模型是否已更改:这就是isDirty 方法。也许在这种情况下,如果您通过编辑我的问题并更改行来提出请求会更好。这也会给你学分。
【解决方案3】:

您应该使用updated 模型事件将列更改与原始事件进行比较,而不是使用updating 事件。请看下面的代码。

AppServiceProvider.php

<?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        User::updated(function($user){
            $changes = array_diff($user->getOriginal(), $user->getAttributes());
            if(array_key_exists('email',$changes)){
                /* do your things. */
            }
        });
    }
}

解释:

  • 获得差异后,您需要使用array_key_exists 检查电子邮件字段是否已更新。

【讨论】:

  • 有一个快捷方式可以检查字段是否已更新:laravel.com/docs/8.x/eloquent#examining-attribute-changes 所以你可以改用if($user-&gt;wasChanged('email')) ^^
  • @D.Petrov 正确,但如果您必须捕获多个字段,那么您需要为每一列正确写入,因此这是处理多列数据的有效方法。
【解决方案4】:

聚会有点晚了,但可能对未来寻求类似解决方案的开发者有所帮助。

我建议使用包 Laravel Attribute Observer,作为污染您的服务提供者或使用 isDirty()wasChanged() 样板填充您的观察者的替代方法。

所以你的用例应该是这样的:

class UserObserver
{


    /**
     * Handle changes to the "email" field of User on "updating" events.
     *
     * @param  \App\User  $user
     * @param string $newValue The current value of the field
     * @param string $oldValue The previous value of the field
     * @return void
     */
    public function onEmailUpdating(User $user, string $newValue, string $oldValue)
    {
      // Your logic goes here...
    }

}

Laravel Attribute Observer 当您要在一个或多个模型上观察大量属性时特别有用。

免责声明:我是 Laravel Attribute Observer 的作者。如果它可以为您节省一些开发时间,请考虑请我喝杯咖啡。

【讨论】:

    猜你喜欢
    • 2021-08-04
    • 1970-01-01
    • 2021-09-24
    • 2019-06-23
    • 2023-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    相关资源
    最近更新 更多