Normally this type of update process is a bit lengthy but efficient and optimal as compared to delete and insert hack, there are many benefits of this approach
- Primary key of a records remains same as compared to other approach which creates a new record and assign a new primary key
- You can track
update_at timestamp which will change on every update while in case of delete/insert the created_at and updated_at will have same values forever
- No unnecessary auto increments added on database side, like sale 1 has 3 records with id 1,2,3 and on update without changing any data the records will be deleted and inserted again and their ids will be 4,5,6 and next auto increment will be set to 7
Lets say in database you already have 2 rows for sale 1
______________________________________________
| id | sales_id | item_id | price | quantity |
----------------------------------------------
| 1 | 1 | 1 | 20 | 5 |
----------------------------------------------
| 2 | 1 | 2 | 10 | 5 |
----------------------------------------------
Let say you have following collection to perform update for sale 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
]
]);
Now if we compare database results and the requested update collection we can see the there is
- one insert for first item in collection because id is null
- one update for second item in collection because id 1 exists in database
- one delete because in requested collection there is no item with id 2 so that needs to be deleted
To perform above updates first we need to collect all items where id is null so we will add these records in database
$addItems = $collection->whereNull('id');
if($addItems->count() > 0){
SaleItem::insert($addItems);
}
For update we need to collect items where id is present and these records will be updated in database as
$updateItems = $collection->whereNotNull('id');
foreach($updateItems as $key => $updateItem) {
SaleItem::where('id', $updateItem->id)->update($updateItem);
}
Or we can use upserts for first and second step as
SaleItem::upsert($updateItems, ['id']);
For delete we can get all ids from collection and perform delete operation on rows that do not match these ids as
$deleteItems = $updateItems->pluck('id');
SaleItem::whereNotIn('id', $deleteItems)->delete();