与删除和插入黑客相比,这种类型的更新过程通常有点冗长但高效且最佳,这种方法有很多好处
- 与创建新记录并分配新主键的其他方法相比,记录的主键保持不变
- 您可以跟踪
update_at 时间戳,该时间戳将在每次更新时更改,而在删除/插入的情况下,created_at 和 updated_at 将永远具有相同的值
- 在数据库端没有添加不必要的自动增量,例如销售 1 有 3 条 ID 为 1、2、3 的记录,在不更改任何数据的情况下更新记录将被删除并再次插入,它们的 ID 将为 4、5、6并且下一个自动增量将设置为 7
假设在数据库中您已经有 2 行待售 1
______________________________________________
| id | sales_id | item_id | price | quantity |
----------------------------------------------
| 1 | 1 | 1 | 20 | 5 |
----------------------------------------------
| 2 | 1 | 2 | 10 | 5 |
----------------------------------------------
假设您有以下收藏来执行更新出售 1
$collection = collect([
[
"id"=> null,
"sales_id"=>1,
"item_id"=> 1,
"price"=>10,
"quantity"=> 0
],
[
"id"=> 1,
"sales_id"=>1,
"item_id"=> 1,
"price"=>10,
"quantity"=> 0
]
]);
现在,如果我们比较数据库结果和请求的更新集合,我们可以看到有
- 因为 id 为空,所以对集合中的第一项进行插入
- 因为数据库中存在 id 1,所以对集合中的第二个项目进行了一次更新
- 一次删除,因为在请求的集合中没有 id 为 2 的项目,因此需要删除
首先要执行上述更新,我们需要收集所有 id 为 null 的项目,以便我们将这些记录添加到数据库中
$addItems = $collection->whereNull('id');
if($addItems->count() > 0){
SaleItem::insert($addItems);
}
为了更新,我们需要收集存在 id 的项目,这些记录将在数据库中更新为
$updateItems = $collection->whereNotNull('id');
foreach($updateItems as $key => $updateItem) {
SaleItem::where('id', $updateItem->id)->update($updateItem);
}
或者我们可以在第一步和第二步中使用upserts
SaleItem::upsert($updateItems, ['id']);
对于删除,我们可以从集合中获取所有id,并对不匹配这些id的行执行删除操作
$deleteItems = $updateItems->pluck('id');
SaleItem::whereNotIn('id', $deleteItems)->delete();