尝试使用特征挂钩模型“更新”事件

Mar*_*ark 0 model traits laravel eloquent

我试图提供一种方法来跟踪用户何时对我的应用程序中的注释部分的模型进行更改。例如,John 修改了 2 个字段,将创建一条注释,说明 John 已从title“我的标题 1”更改为“我的标题 2”,并content从“Lipsum”更改为“Lipsum2”。

这是我创建的一个特征:

<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Model;

trait TrackChanges
{
    public $changes;

    public static function bootChangesTrait()
    {
        static::updating(function($model)
        {
            $this->changes = [];

            foreach($model->getDirty() as $key => $value)
            {
                $original = $model->getOriginal($key);

                 $this->changes[$key] = [
                    'old' => $original,
                    'new' => $value,
                ];
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我在我的模型上成功地使用了这个特性。但是,我不确定如何捕获更改的内容,或者它们是否正常工作。

在我的控制器中我有:

$site = Site::findOrFail($id);

// Catch and cast the is_active checkbox if it's been unselected
if ( ! $request->exists('is_active') )
{
    $request->request->add([ 'is_active' => 0 ]);
}

// // Get rid of the CSRF field & method
$data = $request->except([ '_token', '_method' ]);

$site->update($data);
Run Code Online (Sandbox Code Playgroud)

dd($site->changes)之前和之后都尝试过$site->update($data);,但它只是返回null

我究竟做错了什么?

Eri*_*ker 5

您需要将您的特征中的引导方法更改为bootTrackChanges(). 要启动特征,您需要遵循boot{TraitName}启动方法的命名模式。然后,您需要更改$this特征中的调用,$model以便将更改保存到模型中,因此您的特征应如下所示:

<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Model;

trait TrackChanges
{
    public $changes;

    public static function bootTrackChanges()
    {
        static::updating(function($model)
        {
            $changes = [];

            foreach($model->getDirty() as $key => $value)
            {
                $original = $model->getOriginal($key);

                 $changes[$key] = [
                    'old' => $original,
                    'new' => $value,
                ];
            }

            $model->changes = $changes;
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

另一件需要注意的事情是,如果您在模型中定义了启动方法,请确保您也调用了父启动方法,否则您的特征的启动方法将不会被调用,您的侦听器也不会被注册。我已经花了好几个小时了之前由于忘记调用父方法而在这一点上。在您的模型中,不需要定义启动方法,但如果您确实像这样调用父级:

class MyModel extends Model
{
    use TrackChanges;

    protected static function boot()
    {
        // Your boot logic here

        parent::boot();
    }
}
Run Code Online (Sandbox Code Playgroud)