Drag-and-Drop Sorting for Eloquent Models with Reorderable for Laravel
Last updated on by Paul Redmond
Laravel Reorderable by Richie McMullen adds drag-and-drop sorting to any Eloquent model. It ships with ready-made Blade and Livewire components, persists new positions automatically via a package route, and supports scoping sort order within a parent group.
This package works by applying the HasSortOrder trait and ReorderableContract to your model:
use Atomcoder\LaravelReorderable\Contracts\ReorderableContract;use Atomcoder\LaravelReorderable\Traits\HasSortOrder; class Task extends Model implements ReorderableContract{ use HasSortOrder; protected $fillable = ['title', 'project_id', 'sort_order']; protected string $sortColumn = 'sort_order'; public function getReorderLabel(): string { return $this->title; }}
The trait automatically assigns a sort position on creation and adds an ordered() query scope so you fetch records in the right sequence.
Blade and Livewire Components
The package covers both rendering approaches. Drop an @include into a Blade view, or use the Livewire component — both accept the same options:
Blade:
@include('reorderable::components.list', [ 'items' => $tasks, 'modelClass' => App\Models\Task::class, 'groupColumn' => 'project_id', 'groupValue' => $project->id, 'title' => 'Reorder Tasks', 'listId' => 'project-tasks-list',])
Livewire:
<livewire:reorderable-list :items="$tasks" model-class="App\Models\Task" group-column="project_id" :group-value="$project->id" title="Reorder Tasks" list-id="project-tasks-list"/>
When a user drags an item, the component posts the new order to POST /reorderable/update, which updates the sort column for each record in the database.
Grouped Reordering
The package restricts sort operations to a parent group, so dragging tasks in one project doesn't affect tasks in another. The same scoping is available programmatically via moveToPosition() or reorderFromArray():
$task->moveToPosition( position: 2, groupColumn: 'project_id', groupValue: $task->project_id,); Task::reorderFromArray( orderedIds: [8, 3, 5, 1], groupColumn: 'project_id', groupValue: 12,);
The Generator Command
Instead of wiring up the trait and configuration by hand, reorderable:make scaffolds everything from the command line:
php artisan reorderable:make Task --table=tasks --label=title --column=sort_order
The --label option controls which attribute shows in the drag-and-drop UI, and --column sets the sort column name if you're not using the default sort_order.
Authorization and Events
The configuration accepts a closure to gate access to the update route, so you can tie it to a policy or role check:
'authorize' => function ($request, string $modelClass): bool { return $request->user()?->can('manage-content') ?? false;},
After a successful reorder, the package dispatches ItemsReordered, which carries the model class, the ordered IDs, and the group column and value — useful for cache busting or audit logging.
Requirements
The package requires PHP 8.3+, Laravel 13+, and Livewire 4+.
To learn more, view the source on GitHub.