34

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

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

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

}

每次“updateOrCreate”工作时,它会做 3 件事中的 1 件事:

1)更新模型实例或

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

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

我需要检查 'updateOrCreate' 是否准确地完成了 1(更新),然后执行一些代码。

我该怎么做?

先感谢您!

4

5 回答 5

79

你可以这样想:

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

if(!$tourist->wasRecentlyCreated && $tourist->wasChanged()){
    // updateOrCreate performed an update
}

if(!$tourist->wasRecentlyCreated && !$tourist->wasChanged()){
    // updateOrCreate performed nothing, row did not change
}

if($tourist->wasRecentlyCreated){
   // updateOrCreate performed create
}

评论

从 Laravel 5.5 起,您可以使用wasChangedandisDirty方法检查是否确实发生了更新。

  • isDirty()如果模型属性已更改且未保存,则为真。
  • wasChanged()如果模型属性已更改并保存,则为真。

还有一个属性(不是方法!)wasRecentlyCreated来检查是否创建了用户。

$user = factory(\App\User::class)->create();

$user->wasRecentlyCreated; // true
$user->wasChanged(); // false
$user->isDirty(); // false

$user = \App\User::find($user->id);

$user->wasRecentlyCreated; // false
$user->wasChanged(); // false
$user->isDirty(); // false

$user->firstname = 'Max';

$user->wasChanged(); // false
$user->isDirty(); // true

$user->save();

$user->wasChanged(); // true
$user->isDirty(); // false

//You can also check if a specific attribute was changed:
$user->wasChanged('firstname');
$user->isDirty('firstname');
于 2018-03-18T17:09:57.663 回答
5

很容易确定函数是更新还是插入(检查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
    }
}
于 2017-08-15T22:54:09.907 回答
1

好的,所以我无法为我的场景找到一个好的答案。

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

为了解决这个问题,我创造了一些更轻松的东西,允许在创建和修改之间多出一秒。

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

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

这是我第二次在项目中需要这个,我发布了,因为我刚刚结束了谷歌搜索并回到这个线程寻找相同的答案。

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

于 2020-05-20T04:26:07.627 回答
0

下面的@patricus 提出了一种解决问题的工作方法。虽然@TheFallen 在这里给出了一个使用 Eloquent Events 并且看起来更优雅的解决方案: Laravel Eloquent Events - 如果更新则实现保存模型

于 2017-08-16T09:01:21.297 回答
0

模型属性“wasRecentlyCreated”只有在刚刚创建时才为“真”。

模型中有一个名为“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

            }

        }
于 2019-10-30T07:28:57.587 回答