如何使用Eloquent Laravel更新集合

17

我在DeviceCommand模型之间建立了一对多的关系(每个Device有多个commands)。现在我想使用save()方法更新一组commands。所以,我使用了以下代码:

$device = Device::find(1);
$commands = $device->commands()->whereStatus("pending")->get();

$commands->status = "sent";
$commands->save();

但我得到了一个 FatalErrorException 异常,错误消息为 Call to undefined method Illuminate\Database\Eloquent\Collection::save()

换句话说,我正在寻找在 Eloquent 中与以下 MySQL 查询等价的查询:

UPDATE commands SET status = 'sent' WHERE status = 'pending';

使用 Laravel 4.2

4个回答

26

你可以在 \Illuminate\Database\Eloquent\Builder 对象上尝试使用 update 方法:

$queryBuilder = $device->commands()->whereStatus("pending");
$queryBuilder->update(array("status" => "sent"));

1
更新后我如何获取集合? - user1922137
1
将那行代码赋值给一个变量 - 应该就可以了。 - BenjaminRH
1
谢谢,我编辑了你的答案。在更新“状态”之前,我必须获取数据,因为之后我将得到一个空集合。 - user1922137
10
我对此只有一个评论:变量$collection实际上不是一个集合,而是查询构建器类的一个实例,update()方法并不属于Collection类。 - cdarken
3
这并不应该是一个被接受的答案 - 如上述评论所述,它“起作用”是因为$collection是 QueryBuilder 的实例。 - eithed
显示剩余5条评论

8

由于$commands是一个集合,改变$commands->status的值将不会产生您想要的效果(即将集合中每个项目的status设置为“sent”)。

相反,独立地处理集合中的每个项目:

foreach ($commands as $command)
{
    $command->status = 'sent';
    $command->save();
}

您也可以通过查询构建器更新数据库中的项目:
DB::table('your_table')->where('status', 'pending')->update(array('status' => 'pending'));

或者将其组合为 [你的类]::whereIn('id', $collection->pluck('id'))->update($data)。在这个例子中,它将是 Device::whereIn('id', $commands->pluck('id'))->update(['status' => 'pending']) - eithed
1
这就是为什么我喜欢Doctrine,而讨厌Eloquent的原因。 - JuliSmz
最好尽量避免在循环中进行任何数据库交互,以最小化您的大O数。 - RonnyKnoxville

5

Laravel 7+ 的新功能更新:

toQuery 方法:

  $device = Device::find(1);
  $commands = $device->commands()->whereStatus("pending")->get();
  $commands->toQuery()->update(array("status" => "sent"));

  // you can reload fresh data
  $commands->fresh();

1
toQuery() 是我正在寻找的。 - Yasser CHENIK

2

我知道这可以解决问题,但是对于新用户来说,他们如何更新laravel模型集合?

只需在集合上添加一个更新即可。

Mail::where('to', auth()->user()->email)->update([
    'is_seen' => 1
]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接