【问题标题】:Laravel Command - Method Illuminate\Database\Eloquent\Collection::update does not existLaravel 命令 - 方法 Illuminate\Database\Eloquent\Collection::update 不存在
【发布时间】:2021-08-02 07:00:33
【问题描述】:

我在 Laravel 中创建了一个按任务计划运行的命令。

命令逻辑如下:

public function handle()
{
    $commentNotifications = CommentNotification::where('task_performed', 0)
    ->get();
    
    foreach ($commentNotifications as $commentNotification) {
        //blah blah
    }
    
    $commentNotifications->update(['task_performed' => 1]);


    $this->comment(sprintf('Completed %d CommentNotification(s)', $commentNotifications->count()));
}

但是这会返回以下错误:

方法 Illuminate\Database\Eloquent\Collection::update 不存在。

所以我尝试了这个:

    $commentNotifications->task_performed = 1;
    $commentNotifications->save();

但这返回了:

方法 Illuminate\Database\Eloquent\Collection::save 不存在。

为什么会这样?

【问题讨论】:

  • 您无法更新收藏。在循环中使用$commentNotification->update(['task_performed' => 1]);
  • 但是我在那个循环中有数千条记录。这将导致成千上万的查询......
  • 在这种情况下,创建一个新查询并像这样更新它:CommentNotification::where('task_performed', 0)->update(['task_performed' => 1]);

标签: laravel


【解决方案1】:

这里有两个问题。一是你对 Eloquent 集合的理解,然后你需要用一个查询来更新多条记录。

首先,集合只是一组可以迭代的内存记录。 Eloquent 集合只是它的扩展,这些记录是从数据库中提取的,并且通常具有一组模型作为基础项。它还有一些额外的方法来处理这些模型。

但是,它根本不直接绑定到数据库。这意味着更新之类的功能将不起作用,因此它们不存在。

如果您需要更新集合中的多条记录,则无需先将它们加载到内存中(除非您想在其他地方使用它们)。只需使用 Builder 创建一个查询,然后对该查询调用 update

CommentNotification::where('task_performed', 0)->update(['task_performed' = 1]);

这将创建预期的 SQL 查询:

UPDATE comment_notifications SET task_performed = 1 WHERE task_performed = 0;

编辑 - 回答您关于大规模更新的问题:

如果您只需要更新记录的子集,您只需在更新中添加一个额外的过滤器

CommentNotification::whereIn('id', [1, 2, 3])
    ->where('task_performed', 0)
    ->update(['task_performed' = 1]);

这将仅更新具有这些 ID 的记录,然后仅在未执行任务时更新。如何获取 id 值数组将取决于您。

【讨论】:

  • 我想过使用批量更新。但是,该命令可能需要很长时间才能通过 foreach。当它结束时,新的 CommentNotifications 可能已添加到数据库中。这些不会通过 for 循环,但它们的状态将更新为 task_performed = 1。
  • 然后您需要将它们过滤为仅需要更新的条目。我会更新我的答案。
【解决方案2】:

你正在使用 get() 返回一个集合,因此你不能使用 update 和 save 因为它们是 eloquent 模型类的方法 使用 first() 来获取第一个模型而不是集合,或者使用 foreach 中的更新来更新集合中的每个项目。

save() 和 update() 存在于 Illuminate\Database\Eloquent\Model;

例如

foreach ($commentNotifications as $commentNotification) {
        $commentNotification->update(['task_performed' => 1]);
    }

【讨论】:

  • 这将导致在每个循环上进行数据库查询。我不想那样。
  • 我认为这可以解释您遇到错误的原因,但您仍然可以按照第一条评论中的建议直接使用更新
【解决方案3】:

->get() 返回一个集合。 使用循环到update

public function handle()
{
    $commentNotifications = CommentNotification::where('task_performed', 0)
    ->get();
    
    foreach ($commentNotifications as $commentNotification) {
        $commentNotification->task_performed = 1;
        $commentNotification->save();
    }
    
    $this->comment(sprintf('Completed %d CommentNotification(s)', $commentNotifications->count()));
}

或者,使用Mass Updates

CommentNotification::where('task_performed', 0)->update(['task_performed' => 1]);

【讨论】:

  • 我想过使用批量更新。但是,该命令可能需要很长时间才能通过 foreach。当它结束时,新的 CommentNotifications 可能已添加到数据库中。这些不会通过 for 循环,但它们的状态将更新为 task_performed = 1。
猜你喜欢
  • 1970-01-01
  • 2021-06-08
  • 2021-03-26
  • 1970-01-01
  • 2021-05-30
  • 2020-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多