Laravel检查updateOrCreate是否执行了更新

时间:2017-08-15 22:18:44

标签: laravel updates laravel-events

我的控制器中有以下代码:

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

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

}

每次&#34; updateOrCreate&#34;工作,它做3件事之一:

1)更新模型实例OR

2)创建并保存一个新的OR

3)保持一切不变(如果已存在具有此类值的模型)。

我需要检查是否&lt; updateOrCreate&#39;已完成1(更新),然后执行一些代码。

我该怎么做?

提前谢谢!

6 个答案:

答案 0 :(得分:19)

在Laravel 5.5中,您最终可以检查是否实际使用wasChanged方法完成了更新

$tourist = Tourist::updateOrCreate([...]);

// If true then created otherwise maybe updated
$wasCreated = $tourist->wasRecentlyCreated; 

// If true then the actual row in the database has been modified 
$wasChanged = $tourist->wasChanged();

if(!$wasCreated && $wasChanged){
  // user existed and there were actually updates taking place.
}

// If true then the object `$tourist` has been modified but not saved
$tourist->isDirty();

//You can also check if a specific attribute was changed:
$tourist->wasChanged('name');
$tourist->isDirty('name');

答案 1 :(得分:4)

很容易确定函数是否导致更新或插入(检查wasRecentlyCreated属性)。但是,在使用该功能时,不太容易确定更新是否实际发生(如果模型存在但不脏,则不会执行更新)。我建议不要使用该功能,并自行拆分功能。

这是函数定义:

public function updateOrCreate(array $attributes, array $values = [])
{
    $instance = $this->firstOrNew($attributes);

    $instance->fill($values)->save();

    return $instance;
}

要将其整合到您的代码中,我建议如下:

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

    $tourist->fill($tourist_to_update);

    // if the record exists and the fill changed data, update will be performed
    $updated = $tourist->exists && $tourist->isDirty();

    // save the tourist (insert or update)
    $tourist->save();

    if ($updated) {
        // extra code
    }
}

答案 2 :(得分:1)

好的,所以我找不到适合自己情况的好答案。

我正在使用:$this->created_at == $this->updated_at,但是有时我会在请求的稍后更新记录,这意味着20%的时间created_at和updated_at大约用了1ms。

为了解决这个问题,我创建了一些更轻松的东西,这在创建和修改之间留出了额外的时间。

public function getRecentlyCreatedAttribute()
{
    return $this->wasRecentlyCreated || $this->created_at == $this->updated_at || $this->created_at->diffInSeconds($this->updated_at) <= 1;
}

我现在可以调用$this->recentlyCreated,如果时间差很小(1秒),它将返回true。

这是我第二次在项目中需要此功能,我正在发布,因为我最终对其进行了搜索,然后返回此线程以寻找相同的答案。

如果有人有更优雅的解决方案,嗯。

答案 3 :(得分:0)

下面的@patricus提出了解决问题的有效方法。 虽然@TheFallen在这里提供了一个使用Eloquent Events并且看起来更优雅的解决方案: Laravel Eloquent Events - implement to save model if Updated

答案 4 :(得分:0)

如果您想在更新行时始终执行特定代码,我建议您创建一个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);
}

答案 5 :(得分:0)

只有刚刚创建的模型属性“ wasRecentlyCreated”才是“ true”。

模型中有一个名为“ changes”的属性(它是一个数组),该属性确定模型是否已使用新值更新或是否已按原样保存而未对其属性进行任何更改。

检查以下代码段:

       // Case 1 :  Model Created
        if ($model->wasRecentlyCreated) {

        } else { // Case 2 :  Model Updated

            if (count($model->changes)) { // model has been assigned new values to one of its attributes and saved successfully

            } else { // model has NOT been assigned new values to one of its attributes and saved as is

            }

        }