spatie/eloquent-sortable: Ordered Eloquent Models
Sortable behaviour for Eloquent models
At a glance
- What is it?
- spatie/eloquent-sortable is a Laravel package that adds a configurable ordering column and ordering operations to Eloquent models. It fits applications that need persisted list positions, but its documentation leaves concurrency and missing-record behavior unspecified.
- Who is it for?
- Adopt this package when a Laravel application needs a simple, database-backed order column for Eloquent records. Do not adopt it without reviewing your concurrency requirements, because the README does not explain how simultaneous inserts or incomplete reorder lists are handled.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 119 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A persisted order column for Laravel models
spatie/eloquent-sortable solves a narrow data-modeling problem: keeping an explicit position for each Eloquent record when application users can reorder a collection. It is intended for Laravel applications in which the database, rather than an array in a request or a user interface component, must remember the sequence. The package stores that sequence in an order column and exposes both an ordered query scope and methods for replacing or changing the sequence.
The default column name is `order_column`. A new model receives the highest existing order value plus one when `sort_when_creating` is enabled. On an empty table, the README example says the first saved record gets `1`, the second gets `2`, and the third gets `3`. This is different from sorting by `created_at`: the package gives each record an explicit numeric position that can be changed independently.
The package does not replace Eloquent. It is added to a model through the `Spatie\EloquentSortable\Sortable` interface and the `Spatie\EloquentSortable\SortableTrait` trait. That makes it suitable for models that represent ordered items such as navigation entries, dashboard cards, lessons, or configuration sections. The documentation does not describe drag-and-drop interfaces, validation, authorization, or a complete UI, so the package should not be mistaken for a front-end ordering system.
How SortableTrait calculates and applies positions
The documented data flow begins when a model using the trait is created. If creation sorting is enabled, the package calculates the maximum value in the configured order column for that model and assigns the next value. The `ordered()` scope then fetches records in the configured order. The README describes the mechanism, but it does not publish the SQL or explain transaction behavior, locking, or collision handling, so applications with concurrent writes should not assume that the calculation is serialized.
Reordering is performed at model-class level with `setNewOrder()`. Passing `[3, 1, 2]` assigns positions `1`, `2`, and `3` to the records identified by those primary-key values. A second argument changes the starting number, so `[3, 1, 2]` with a starting value of `10` produces `11`, `12`, and `13`. The package also supports a closure as the fourth argument for modifying the query that will be executed. The README gives `withoutGlobalScope(new ActiveScope)` as the example use case.
The primary key is not the only possible identifier. `setNewOrderByCustomColumn()` accepts a column name and an ordered list, which allows UUID-based ordering. The documented example uses the `uuid` column. This is useful for models whose identifiers are not predictable integers, but the package still requires the application to provide a stable, unique value for each record. The README does not specify what happens when a supplied identifier is absent or duplicated.
Installing eloquent-sortable and configuring a model
The README says to install the package through Composer. The documented Laravel service-provider registration is automatic in Laravel 5.5 and above. Older Laravel versions require the provider entry shown below. The configuration file is optional, but publishing it gives the application a visible place to set the column name, creation behavior, and timestamp handling.
Install the package:
composer require spatie/eloquent-sortableFor older Laravel versions, add the service provider in `config/app.php`:
'providers' => [
...
Spatie\EloquentSortable\EloquentSortableServiceProvider::class,
];The README does not document a Laravel version requirement for the current release. It only says that Laravel 6.x or PHP 7.x users should use version 3.x. Check the package's Composer metadata and the release being installed before using the unversioned command in a legacy application.
Publishing defaults and preparing the model
The optional configuration file controls the default order column, whether new records are sorted automatically, and whether `setNewOrder` should leave `updated_at` untouched. The README calls the timestamp option `ignore_timestamps`. Publishing the file is useful when the application wants an explicit configuration rather than relying on defaults.
Publish the configuration with:
php artisan vendor:publish --tag=eloquent-sortable-configThe documented configuration has these keys:
return [
'order_column_name' => 'order_column',
'sort_when_creating' => true,
'ignore_timestamps' => false,
];The model then implements the interface and uses the trait. The model can override the column and creation setting locally:
class MyModel extends Model implements Sortable
{
use SortableTrait;
public $sortable = [
'order_column_name' => 'order_column',
'sort_when_creating' => true,
];
}The database table must contain the configured order column. The README does not provide a migration command or migration schema, so it does not claim that the package creates the column automatically. If the application uses another name, set `order_column_name` consistently in configuration or in the model.
A first ordered query and reorder operation
The shortest documented first use is to save three new records and retrieve them with the ordered scope. With an empty table and automatic creation sorting enabled, the records receive positions `1`, `2`, and `3` in creation order. The scope returns the records in that order.
$myModel = new MyModel();
$myModel->save();
$myModel = new MyModel();
$myModel->save();
$myModel = new MyModel();
$myModel->save();
$orderedRecords = MyModel::ordered()->get();To replace the order, pass the desired sequence of primary keys to `setNewOrder()`:
MyModel::setNewOrder([3, 1, 2]);The operation is class-oriented, so it changes stored positions rather than returning a collection for the caller to sort in memory. For UUIDs, use the custom-column form:
MyModel::setNewOrderByCustomColumn('uuid', [
'7a051131-d387-4276-bfda-e7c376099715',
'40324562-c7ca-4c69-8018-aff81bff8c95',
'5dc4d0f4-0c88-43a4-b293-7c7902a3cfd1'
]);This is a good fit when the application already has an endpoint or service that receives a complete ordered list and needs to persist it. It is not a documented solution for partial moves, drag events, or automatic conflict resolution.
Concurrency, upgrade cost, and the manual alternative
The main limitation is that the README describes a maximum-plus-one assignment without documenting database locks, transactions, unique constraints, or retries. Two requests that create records at the same time could therefore require application-level coordination if duplicate or skipped positions are unacceptable. The package does not document a failure mode for duplicate identifiers, missing identifiers, partial lists, or records filtered by global scopes. Those cases need direct examination before the package becomes part of a multi-user editing service.
A real alternative is to keep the order column but manage it directly with Eloquent queries and a scope written by the application. That approach gives the application control over transaction boundaries, locking, authorization, and validation. The trade-off is that the developer must implement and maintain the creation, ordering, and reordering logic that `SortableTrait` supplies. Spatie's package is more convenient for the simple case where the documented sequence rules are sufficient.
The MIT license allows use and modification under that license, subject to its terms. No legal advice is offered here. The repository is not archived, and the last push was on 2026-06-26. Releases include 5.0.1 on 2026-02-21 and 4.5.2 on 2025-08-25, so adopting the current release should include checking its changelog and Composer constraints against the existing Laravel application.
Editorial conclusion
Adopt this package when a Laravel application needs a simple, database-backed order column for Eloquent records. Do not adopt it without reviewing your concurrency requirements, because the README does not explain how simultaneous inserts or incomplete reorder lists are handled. Verify first that your database schema, model events, global scopes, and chosen order identifiers match the package configuration.
Frequently asked questions
How do I install spatie/eloquent-sortable in a Laravel application?
Run `composer require spatie/eloquent-sortable`. In Laravel 5.5 and above, the README says the service provider is registered automatically.
What column does spatie/eloquent-sortable use for ordering?
The default is `order_column`. You can change it through `order_column_name` in `config/eloquent-sortable.php` or in the model's `$sortable` configuration.
How do I reorder records with spatie/eloquent-sortable?
Call `setNewOrder()` with model identifiers in the desired sequence, or use `setNewOrderByCustomColumn()` when identifiers such as UUIDs are stored in another column. The README also documents an optional starting order argument.
Does spatie/eloquent-sortable handle simultaneous record creation?
The README describes assigning the maximum existing order plus one, but it does not document locking, transactions, retries, or collision behavior. Those details are not confirmed by the available documentation.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/spatie-eloquent-sortable)Was this useful?