【问题标题】:Laravel check if updateOrCreate performed updateLaravel 检查 updateOrCreate 是否执行了更新
【发布时间】:2018-01-23 22:31: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(更新),然后执行一些代码。

我该怎么做?

提前谢谢你!

【问题讨论】:

  • 您可以使用updated 模型事件(仅在模型实际更新时触发),还是应该仅在这组特定代码更新模型时运行此额外代码?
  • @patricus,谢谢!我使用了更新的模型事件,但我管理它只是为了做一些简单的事情,比如 public function handle(TouristUpdated $event) { dump($event); (这是我的听众的代码)。我不知道如何指示侦听器将一些逻辑添加到我的控制器中。逻辑实际上应该是创建一个包含所有触发“更新”事件的 $tourist_to_update 的数组。希望我解释清楚。

标签: laravel updates laravel-events


【解决方案1】:

你可以这样算:

$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 起,您可以使用 wasChangedisDirty 方法检查是否确实发生了更新。

  • 如果模型属性已更改且未保存,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');

【讨论】:

    【解决方案2】:

    好的,所以我找不到适合我的场景的好答案。

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

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

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      模型中有一个名为“changes”的属性(它是一个数组),它决定了模型是用新值更新还是按原样保存而不对其属性进行任何更改。

      检查以下代码sn -p:

             // 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
      
                  }
      
              }
      

      【讨论】:

        【解决方案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
            }
        }
        

        【讨论】:

        • 谢谢!我已经考虑过了,但是你解释得很详细。我仍然希望有机会使用“更新”模型事件。但如果不是 - 我会选择这个答案为“正确”。
        • 你能解释一下你的第一句话It is pretty easy to determine if the function resulted in an update or an insert.吗?因为这就是我想要的,我不知道如何得到。
        • NVM 我已经找到了:stackoverflow.com/questions/44238257/…
        • @Adam 很高兴你找到它。我继续更新我的答案以提及它,以防万一其他人也来到这里想知道。谢谢。
        • 现在有一个名为wasChanged() 的函数正在做这项工作。
        【解决方案5】:

        @patricus 下面提出了一种解决问题的工作方法。 虽然@TheFallen 这里给出了一个使用 Eloquent Events 的解决方案,而且看起来更优雅: Laravel Eloquent Events - implement to save model if Updated

        【讨论】:

          猜你喜欢
          • 2017-10-29
          • 1970-01-01
          • 2019-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-06
          • 1970-01-01
          • 2015-03-08
          相关资源
          最近更新 更多