PHPackages                             davidgut/sortable - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. davidgut/sortable

ActiveLibrary[Database &amp; ORM](/categories/database)

davidgut/sortable
=================

A sortable trait for Laravel models

v3.1.0(1mo ago)13MITPHPPHP ^8.2

Since Dec 15Pushed 1mo agoCompare

[ Source](https://github.com/davidgut/sortable)[ Packagist](https://packagist.org/packages/davidgut/sortable)[ RSS](/packages/davidgut-sortable/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (8)Versions (8)Used By (0)

Laravel Sortable
================

[](#laravel-sortable)

Drag-and-drop sorting for your Eloquent models — backend and frontend included.
No dependencies, no build step required for the JS, just install and go.

Supports Laravel 11, 12 &amp; 13.

Quick Start
-----------

[](#quick-start)

```
composer require davidgut/sortable
```

Add a `sort_order` column to any table you want to sort:

```
$table->integer('sort_order')->nullable();
```

Then implement the contract on your model:

```
use DavidGut\Sortable\Contracts\Sortable;
use DavidGut\Sortable\Traits\SortableTrait;

class Post extends Model implements Sortable
{
    use SortableTrait;
}
```

That's it for the backend. New records automatically get the next sort order, and the package registers a `PUT /sortable/{model}/{id}` route for you.

### Frontend

[](#frontend)

Publish the included JavaScript:

```
php artisan vendor:publish --tag=sortable-assets
```

Import it in your `app.js`:

```
import SortableList from './vendor/sortable/sortable';

SortableList.start();
```

Mark up your list:

```

    @foreach($posts as $post)

            {{ $post->title }}

    @endforeach

```

This produces:

```

        ⠿
        My First Post

    ...

```

All three components accept `as` to change the rendered element (defaults: `ul`, `li`, `span`), and forward any extra attributes:

```

    @foreach($posts as $post)

            ☰
            {{ $post->title }}

    @endforeach

```

#### Without Components

[](#without-components)

If you prefer plain HTML, use the `@sortableUrl` directive or the `->sortableUrl()` method:

```

    @foreach($posts as $post)

            ⠿
            {{ $post->title }}

    @endforeach

```

Make sure you have a `` tag in your layout — the JS reads it for requests.

Done. Your list is now sortable.

---

Configuration
-------------

[](#configuration)

### Registering Models

[](#registering-models)

Publish the config:

```
php artisan vendor:publish --tag=sortable-config
```

Map your models in `config/sortable.php`:

```
'models' => [
    'posts' => \App\Models\Post::class,
],
```

> In non-production environments the package will also try to resolve `App\Models\{Name}` automatically, so you can skip this step during development. In production, only explicitly registered models are allowed.

### Custom Sort Column

[](#custom-sort-column)

The default column is `sort_order`. To change it, set the property on your model:

```
class Post extends Model implements Sortable
{
    use SortableTrait;

    protected $sortColumn = 'order';
}
```

### Scoped Sorting

[](#scoped-sorting)

Need separate sort orders per group? For example, sorting posts within each category independently:

```
class Post extends Model implements Sortable
{
    use SortableTrait;

    protected ?string $sortScope = 'category_id';
}
```

Each `category_id` will now have its own sort sequence starting from 0.

### Custom Sort Queries

[](#custom-sort-queries)

For more advanced cases, override `sortQuery()`:

```
protected function sortQuery(): Builder
{
    return parent::sortQuery()->where('is_active', true);
}
```

### Custom Routes

[](#custom-routes)

The package auto-registers routes with `web` middleware. If you need to customise them:

```
php artisan vendor:publish --tag=sortable-routes
```

### Query Scope

[](#query-scope)

Retrieve records in sorted order:

```
Post::sorted()->get();
Post::sorted('desc')->get();
```

---

Authorization
-------------

[](#authorization)

By default, only users where `$user->isAdmin()` returns `true` can re-sort items. Override this per model:

```
public function canBeSortedBy($user): bool
{
    return $user->id === $this->user_id;
}
```

---

SPA / Livewire
--------------

[](#spa--livewire)

`SortableList.start()` returns the created instances. Call `SortableList.stop()` to tear them down on navigation:

```
const instances = SortableList.start();

// Later, on page leave:
SortableList.stop();
```

---

License
-------

[](#license)

MIT

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance89

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~17 days

Recently: every ~0 days

Total

7

Last Release

53d ago

Major Versions

v1.0.0 → v2.0.02025-12-16

v2.0.1 → v3.0.02026-03-26

### Community

Maintainers

![](https://www.gravatar.com/avatar/a1163b75d4f25d863e452d8118eb3b266c29656783beb9a9c02c9498ced60b8e?d=identicon)[davidgut\_](/maintainers/davidgut_)

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/davidgut-sortable/health.svg)

```
[![Health](https://phpackages.com/badges/davidgut-sortable/health.svg)](https://phpackages.com/packages/davidgut-sortable)
```

###  Alternatives

[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[cybercog/laravel-love

Make Laravel Eloquent models reactable with any type of emotions in a minutes!

1.2k302.7k1](/packages/cybercog-laravel-love)[cviebrock/eloquent-taggable

Easy ability to tag your Eloquent models in Laravel.

567694.8k3](/packages/cviebrock-eloquent-taggable)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)[genealabs/laravel-pivot-events

This package introduces new eloquent events for sync(), attach(), detach() or updateExistingPivot() methods on BelongsToMany relation.

1404.9M8](/packages/genealabs-laravel-pivot-events)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
