take a look at this table first then i'll explain.
parent {
id:number;
name:string;
}
child {
id:number;
name:string;
parent_id:number; //foreignKey to parent table
}
and this is the API request to do an update to backend
Request = {
id:1; //parent id
name:'update the name';
childs:[
{
id:1,
name:'child 1'
},
{
id:null, //if null its mean i have to create this child
name:'child 2'
}
]
}
so if the Request.childs have id on each item then i have to update the child, but if its doesn't have an id i have to create a new child.
And if child doesn't exist in Request.childs i have to delete it.
my question is how do i delete the previous child that doesn't exist in Request.childs ?
what i am doing now is i am deleting all the child that belongs to the parent_id and create a new child based on Request, but since child have soft delete on all the deleted child will get stacked in the database.
what currently i am doing
{
child::where('parent_id',Request->id)->delete();
foreach($Request->childs as $item){
child::create['name'=>$item->name,'parent_id'=>$Request->id];
}
}
what i probably i have to do
foreach($Request->childs as $item){
if($item->id == null){
child::create['name'=>$item->name,'parent_id'=>$Request->id];
}
child::find($item->id)->update['name'=>$item->name];
}
i just don't know how to delete the previous child record without deleting everything ?
This is the way I would do it:
public function patch(Request $request)
{
Child::whereNotIn('id', array_column($request->childs, 'id'))->delete();
Child::upsert([
$request->childs
], ['id'], ['name']);
}
If you don't want to soft delete the child you can apply forceDelete()
as below:
child::where('parent_id',Request->id)->forceDelete();
foreach($Request->childs as $item) {
if($item->id == null){
child::create['name'=>$item->name,'parent_id'=>$Request->id];
}
child::find($item->id)->update['name'=>$item->name];
}
You just need to get the ids from the database and compare
{
$childIds = child::where('parent_id',Request->id)->pluck('id')->toArray();
$flippedChildIds = array_flip($childIds);// we flip the keys and values for easy unsetting.
$childsToBeInsertedOrUpdated = [];
foreach($Request->childs as $item){
//add deleted at in case a child was deleted and need to be re activated
// if you dont want the child to be reactivated, remove "deleted_at" from both arrays
$childsToBeInsertedOrUpdated[] = ['id' => $item->id, 'name' => $item->name, 'deleted_at' => null];
//if exists, remove from the to be deleted childs
unset($flippedChildIds[$item->id]));
}
//only two request for delete and update/create (faster)
if ($flippedChildIds) {
Child::whereIn('id', array_keys($flippedChildIds))->delete();
}
if ($childsToBeInsertedOrUpdated) {
Child::upsert($childsToBeInsertedOrUpdated, ['id'], ['name', 'deleted_at']);
}
}