debug404 / laravel-ranker
High-performance Eloquent drag-and-drop item sorting and reordering package for Laravel.
Requires
- php: ^8.1|^8.2|^8.3|^8.4
- illuminate/database: ^9.0|^10.0|^11.0|^12.0
- illuminate/http: ^9.0|^10.0|^11.0|^12.0
- illuminate/routing: ^9.0|^10.0|^11.0|^12.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-10-18 08:03:05 UTC
README
A high-performance, developer-friendly drag-and-drop ordering, ranking, and Kanban management package for Laravel Eloquent models.
✨ Features
- 🚀 High Performance Batching: Updates complete reordering sequences in a single atomic
UPDATE ... CASE WHENSQL query. - 🗂️ Cross-Group & Kanban Boards: Move records across columns/categories (
moveToGroup()) and automatically re-index both origin and target partitions. - 🎯 Seamless Eloquent Auto-Ordering: Automatically calculates and assigns sequence numbers upon model creation.
- ⚡ Gap Normalization & CLI Repair: Eliminate fragmentation gaps (e.g.
1, 5, 9➔1, 2, 3) viaModel::normalizeOrder(),normalize_on_delete, andphp artisan ranker:normalize. - 📢 Dedicated Eloquent Events: Dispatches
Ranker\Events\OrderChangedandRanker\Events\ItemMovedfor audit logs, webhooks, and cache invalidation. - 🔄 Directional & Positional Helpers: Built-in
moveOrderUp(),moveOrderDown(),moveToPosition($pos),moveToStart(),moveToEnd(), andswapOrderWith(). - 🌐 Ready-to-use API Endpoint: Includes
RankerController, form request validation, andRoute::ranker()macro.
📦 Installation
Install the package via Composer:
composer require debug404/laravel-ranker
Publish the package configuration file (optional):
php artisan vendor:publish --tag="ranker-config"
⚙️ Configuration
The published config file (config/ranker.php) allows you to customize defaults:
return [ // Default column used to store the sort index 'order_column_name' => 'order_column', // Starting index for the sequence (1 or 0) 'start_order' => 1, // Auto-calculate order on creation 'sort_when_creating' => true, // Auto-close gaps when records are deleted (soft or hard) 'normalize_on_delete' => false, // Placement for restored soft-deleted models ('end', 'start', or 'original') 'restore_to' => 'end', // Whitelist of models allowed in universal reorder endpoint 'allowed_models' => [ \App\Models\Project::class, \App\Models\Task::class, ], ];
🚀 Quick Start
1. Database Migration
Add an integer column (e.g. order_column) to your table:
Schema::table('tasks', function (Blueprint $table) { $table->integer('order_column')->nullable()->index(); });
2. Prepare Your Model
Implement Ranker\Contracts\Sortable and use the Ranker\Traits\HasSortableOrder trait:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Ranker\Contracts\Sortable; use Ranker\Traits\HasSortableOrder; class Task extends Model implements Sortable { use HasSortableOrder; protected $fillable = ['title', 'status', 'project_id', 'order_column']; /** * Optional custom configuration per model: */ public array $sortable = [ 'order_column_name' => 'order_column', 'sort_when_creating' => true, 'normalize_on_delete' => true, 'group_by' => ['project_id', 'status'], // Multi-tenant / Kanban grouping ]; }
📖 Usage & Examples
Querying Ordered Records
// Fetch tasks sorted in ascending order (default) $tasks = Task::ordered()->get(); // Fetch tasks sorted in descending order $tasks = Task::orderedDesc()->get();
Batch Reordering (Drag-and-Drop)
Pass an array of primary keys in the newly sorted sequence:
use App\Models\Task; // Reorders IDs: 10 becomes order 1, 4 becomes order 2, 8 becomes order 3 Task::setNewOrder([10, 4, 8]);
🗂️ Kanban Cross-Column / Cross-Group Moving
Move an item to a different category/status and insert it at a specific position:
$task = Task::find(12); // Move from 'todo' to 'in_progress' at position 1 (shifts other in_progress items down) $task->moveToGroup(['status' => 'in_progress'], newPosition: 1);
Position Manipulation & Normalization
$task = Task::find(4); // Move to exact position (e.g., position 3) $task->moveToPosition(3); // Directional helpers $task->moveOrderUp(); $task->moveOrderDown(); $task->moveToStart(); $task->moveToEnd(); $task->swapOrderWith($otherTask); // Compact gaps in order sequence (e.g. 1, 4, 9 -> 1, 2, 3) Task::normalizeOrder(['project_id' => 5]);
🛠️ CLI Management Commands
Normalize Sequence Gaps
Repair and normalize order gaps across all records or scoped groups:
# Normalize global orders for a model php artisan ranker:normalize "App\Models\Task" # Normalize orders partitioned by grouping column php artisan ranker:normalize "App\Models\Task" --group=project_id
📢 Events & Webhooks
Laravel Ranker dispatches events for listening to sequence changes:
| Event | Dispatched When | Payload Properties |
|---|---|---|
Ranker\Events\OrderChanged |
Batch setNewOrder() finishes |
$event->modelClass, $event->ids, $event->scope |
Ranker\Events\ItemMoved |
Single item moves or swaps | $event->model, $event->previousPosition, $event->newPosition |
🌐 API Endpoint Integration
Register the Route::ranker() macro in routes/web.php or routes/api.php:
Route::ranker('tasks/reorder')->name('tasks.reorder');
Drag-and-Drop Payload:
{
"model": "App\\Models\\Task",
"items": [4, 1, 9]
}
Kanban Cross-Group Move Payload:
{
"model": "App\\Models\\Task",
"items": [4],
"target_group": { "status": "done" },
"position": 1
}
📄 License
The MIT License (MIT). Please see License File for more information.