To begin using atomcoder/laravel-reorderable, follow these minimal steps:
Install the package:
composer require atomcoder/laravel-reorderable
php artisan reorderable:install
This publishes the config, views, and migration stub.
Add a sort column to your target table (e.g., sort_order):
Schema::table('tasks', function (Blueprint $table) {
$table->unsignedInteger('sort_order')->default(0)->index();
});
Make your model reorderable:
use Atomcoder\LaravelReorderable\Contracts\ReorderableContract;
use Atomcoder\LaravelReorderable\Traits\HasSortOrder;
class Task extends Model implements ReorderableContract
{
use HasSortOrder;
protected $fillable = ['title', 'sort_order'];
public function getReorderLabel(): string { return $this->title; }
}
Whitelist your model in config/reorderable.php:
'allowed_models' => [
App\Models\Task::class,
],
Fetch and render items:
$tasks = Task::ordered()->get();
@include('reorderable::components.list', [
'items' => $tasks,
'modelClass' => App\Models\Task::class,
])
First use case: Implement drag-and-drop sorting for a list of tasks in a project. Use the ordered() scope to fetch tasks and render them with the Blade component.
Model Setup:
HasSortOrder trait and implement ReorderableContract.getReorderLabel() for UI display text.$sortColumn or getDefaultReorderGroupColumn().Fetching Data:
ordered() scope to ensure correct sort order:
$items = Model::where('group_column', $value)->ordered()->get();
Rendering UI:
@include('reorderable::components.list', [
'items' => $items,
'modelClass' => Model::class,
'groupColumn' => 'project_id',
'groupValue' => $project->id,
])
<livewire:reorderable-list
:items="$items"
model-class="Model"
group-column="project_id"
:group-value="$project->id"
/>
Grouped Reordering:
groupColumn and groupValue in both the query and UI.Programmatic Reordering:
$item->moveToPosition(3, 'project_id', $projectId);
Model::reorderFromArray([5, 1, 3], 'project_id', $projectId);
authorize config callback to restrict reordering:
'authorize' => function ($request, $modelClass) {
return $request->user()->can('reorder-' . $modelClass);
},
ItemsReordered to trigger side effects (e.g., cache updates):
Event::listen(ItemsReordered::class, function ($event) {
Cache::forget("reorderable-{$event->modelClass}");
});
resources/views/vendor/reorderable/components/list.blade.php.Missing CSRF Token:
<meta name="csrf-token"> in the <head> and @stack('scripts') in the layout. Forgetting this breaks drag-and-drop functionality.Incorrect Grouping:
groupColumn/groupValue are misconfigured, reordering may affect items outside the intended group. Always verify with:
$items = Model::where('group_column', $value)->ordered()->get();
Sort Column Conflicts:
$sortColumn matches the database column name. Defaults to sort_order but can be customized per model.Livewire Hydration:
public properties for props:
public $items;
public $modelClass;
Demo Route:
/reorderable/demo route is disabled by default (demo.enabled = false). Enable only for testing./reorderable/update (default route) to verify the payload structure:
{
"model": "App\\Models\\Task",
"items": [1, 3, 2],
"group_column": "project_id",
"group_value": 5
}
php artisan event:listen to debug ItemsReordered events:
php artisan event:listen Atomcoder\LaravelReorderable\Events\ItemsReordered
Model::where('project_id', $projectId)->ordered()->get();
Custom UI:
vendor/atomcoder/laravel-reorderable/resources/views to resources/views/vendor/reorderable.Custom Sort Logic:
moveToPosition() or reorderFromArray() in your model for custom behavior:
public function moveToPosition($position, $groupColumn = null, $groupValue = null)
{
// Custom logic here
parent::moveToPosition($position, $groupColumn, $groupValue);
}
API Integration:
reorderFromArray() logic in API endpoints:
public function updateOrder(Request $request)
{
$this->validate($request, ['items' => 'required|array']);
Model::reorderFromArray($request->items, 'group_column', $request->group_value);
return response()->json(['success' => true]);
}
Testing:
reorderFromArray() method in tests to set up sorted data:
public function testReordering()
{
Model::reorderFromArray([3, 1, 2]);
$this->assertDatabaseHas('tasks', ['id' => 1, 'sort_order' => 2]);
}
route_prefix in config affects all package routes (e.g., /custom/reorderable/update).middleware in config includes web for CSRF protection. Add auth if reordering should be restricted:
'middleware' => ['web', 'auth'],
How can I help you explore Laravel packages today?