Skip to content

Commit

Permalink
Merge pull request #5342 from Laravel-Backpack/use-upsert-for-reorder
Browse files Browse the repository at this point in the history
use upsert instead of 2 queries per row
  • Loading branch information
pxpm authored Jul 17, 2024
2 parents 6141ed3 + b40ec8f commit e40e01b
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions src/app/Library/CrudPanel/Traits/Reorder.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,40 @@ trait Reorder
*/
public function updateTreeOrder($request)
{
$count = 0;
$primaryKey = $this->model->getKeyName();

\DB::beginTransaction();
foreach ($request as $key => $entry) {
if ($entry['item_id'] != '' && $entry['item_id'] != null) {
$item = $this->model->where($primaryKey, $entry['item_id'])->update([
'parent_id' => empty($entry['parent_id']) ? null : $entry['parent_id'],
'depth' => empty($entry['depth']) ? null : $entry['depth'],
'lft' => empty($entry['left']) ? null : $entry['left'],
'rgt' => empty($entry['right']) ? null : $entry['right'],
]);
// we use the upsert method that should update the values of the matching ids.
// it has the drawback of creating new entries when the id is not found
// for that reason we get a list of all the ids and filter the ones
// sent in the request that are not in the database
$itemKeys = $this->model->query()->select($primaryKey)->get()->pluck($primaryKey);

$count++;
}
}
\DB::commit();
$reorderItems = collect($request)->filter(function ($item) use ($itemKeys) {
return $item['item_id'] !== '' && $item['item_id'] !== null && $itemKeys->contains($item['item_id']);
})->map(function ($item) use ($primaryKey) {
$item[$primaryKey] = (int) $item['item_id'];
$item['parent_id'] = empty($item['parent_id']) ? null : (int) $item['parent_id'];
$item['depth'] = empty($item['depth']) ? null : (int) $item['depth'];
$item['lft'] = empty($item['left']) ? null : (int) $item['left'];
$item['rgt'] = empty($item['right']) ? null : (int) $item['right'];
// we are not touching those two columns on update, but we need them to be present
// for the upsert query to work. they will just be ignored and not touched.
$item['name'] = '';
$item['slug'] = '';

return $count;
// unset mapped items properties.
unset($item['item_id'], $item['left'], $item['right']);

return $item;
})->toArray();

$this->model->upsert(
$reorderItems,
$primaryKey,
['parent_id', 'depth', 'lft', 'rgt']
);

return count($reorderItems);
}

/**
Expand Down

0 comments on commit e40e01b

Please sign in to comment.