Laravel model relationships and model events

Udd*_*ers 4 php relational-database laravel eloquent

I am building a notification system at the moment, and the notifications get delivered via model events. Some of the notifications are dependent on things happening with the models relationships.

Example: I have a project model that has a one:many relationship with users,

public function projectmanager() {
    return $this->belongsToMany('User', 'project_managers');
}
Run Code Online (Sandbox Code Playgroud)

I am wanting to monitor for changes on this relationship in my project model events. At the moment, I am doing this by doing this following,

$dirtyAttributes = $project->getDirty();
foreach($dirtyAttributes as $attribute => $value) {
   //Do something
}
Run Code Online (Sandbox Code Playgroud)

这是在::updating模型事件中运行,但只查看模型属性而不是任何关系数据,是否可以获取旧关系数据和新关系数据进行比较和处理?

Lei*_*ith 5

您应该为此使用观察者类

这个 SO answer已经相当简单和很好地涵盖了这一点,尽管该答案使用了一个稍微旧的方法,其中类本身需要调用其观察者。当前版本的文档(本答案为 5.3)建议在您的应用程序服务提供者中注册观察者,在您的示例中,它类似于:

<?php
namespace App\Providers;

use App\Project;
use App\Observers\ProjectObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Project::observe(ProjectObserver::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

为了评估新模型值与仍在关系数据库中的旧值之间的差异,Laravel 提供了以下方法:getDirty()getOriginal()

所以你的观察者看起来像:

<?php

namespace App\Observers;

use App\Project;

class ProjectObserver
{
    /**
     * Listen to the Project updating event.
     *
     * @param  Project $project
     * @return void
     */
    public function updating(Project $project)
    {
        $dirtyAttributes = $project->getDirty();
        $originalAttributes = $project->getOriginal();
        // loop over one and compare/process against the other
        foreach ($dirtyAttributes as $attribute => $value) {
            // do something with the equivalent entry in $originalAttributes
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我知道已经过去三年了,但我有点困惑为什么这个答案被接受。它没有解决如何获取_相关_字段的脏/原始值的问题。getDirty 和 getOriginal 不包含任何有关关系的信息(例如外键除外)。 (2认同)
  • @CharlesWood 对关系本身的更改由外键确定,如果更改,它将成为原始/脏值的一部分(即哪个用户被更改为项目经理)。如果您想检测相关模型的更改(例如,您想知道作为经理的用户是否更改了他们的名字?),那么您将有一个用户模型的观察者,并对其中的更改执行一些操作。如果您出于某种原因想要操作项目来观察相关模型的更改,您可以使用“getRelations()”或“relationsToArray()”。也许“getTouchedRelations()”,取决于。 (2认同)