Laravel Eloquent 事件 - 更新后保存模型

Laravel Eloquent Events - implement to save model if Updated

我在控制器中有这样的代码:

for($i=0; $i<$number_of_tourists; $i++) {

$tourist = Tourist::updateOrCreate(['doc_number' => $request['doc_number'][$i]],
$tourist_to_update);

}

因此,updateOrCreate 方法可以 1) 更新记录,2) 创建新记录 3) 如果 $tourist_to_update 等于数据库中已有的记录,则保持记录不变。

我想将 $tourist_to_update 保存到 $array[] 中,仅当正在更新“游客”table 中的记录时(而不是当已创建新记录或没有任何变化)。

据我所知,有 Eloquent 事件 https://laravel.com/docs/5.4/eloquent#eventsupdatingupdated 事件,似乎符合我的需求。

问题是我看了几个教程,但仍然不明白如何使用它们。

我知道如何在 Tourist 模型中注册 Eloquent 事件:

protected static function boot()
{
    parent::boot();

    static::updating(function ($model) {

    });
}

谁能解释一下我如何通过 Eloquent 事件实现我的目标?

提前致谢。

如果模型已创建,属性 wasRecentlyCreated 将设置为 true,因此您可以通过以下方式检查模型是新的还是更新的:

$updated = [];

for($i = 0; $i < $number_of_tourists; $i++) {
    $currentTourist = ['doc_number' => $request['doc_number'][$i]];
    $tourist = Tourist::updateOrCreate($currentTourist, $tourist_to_update);

    if ( $tourist->wasRecentlyCreated ) {
        continue; // Go to next loop if this tourist was created now
    }

    $updated[] = $tourist;
}

这是一种稍微复杂一些的方法,但如果您只想获取数据已更改的更新记录,这是可行的。在您的控制器方法中添加:

app()->singleton('touristsCollector', function ($app) {
    $collector = new \stdClass;
    $collector->updated = [];

    return $collector;
});

for($i = 0; $i < $number_of_tourists; $i++) {
    $tourist = Tourist::updateOrCreate(
        ['doc_number' => $request['doc_number'][$i]],
        $tourist_to_update
    );
}

$collector = resolve('touristsCollector');
var_dump( $collector->updated ); // Only updated tourists which have data changed

这基本上会向应用程序容器添加一个标准 PHP class,它将收集模型事件中所有更新的游客。在您的模型中添加:

protected static function boot()
{
    parent::boot();

    static::updated(function ($model) {
        $collector = resolve('touristsCollector');
        $collector->updated[] = $model;
    });
}

这基本上会从应用程序容器中获取 PHP class,仅当其某些属性已更新时添加游客模型。

如果你总是想在 tourist table 中的一行更新时执行特定代码,我建议创建一个 observer 来监听 updatedcreate来电。

<?php

namespace App\Observers;

use App\Tourist;

class TouristObserver
{
    /**
     * Listen to the User created event.
     *
     * @param  \App\User  $user
     * @return void
     */
    public function created(Tourist $user)
    {
        // this will always trigger when you created a new entry
    }

    /**
     * Listen to the User deleting event.
     *
     * @param  \App\Tourist $user
     * @return void
     */
    public function updated(Tourist $user)
    {
        // this will always trigger when actually a row was updated
    }
}

您所要做的就是像这样在 AppServiceProvider 中注册观察者:

public function boot()
{
    Tourist::observe(\App\Observer\TouristObserver::class);
}