PHPackages                             svv-team/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. svv-team/sortable

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

svv-team/sortable
=================

Adds sortable behavior and ordering to Laravel Eloquent models. Grouping and many to many supported.

7.0.1(6y ago)03MITPHPPHP &gt;=7.2.5

Since Jun 28Pushed 5y agoCompare

[ Source](https://github.com/SVV-team/rutorika-sortable)[ Packagist](https://packagist.org/packages/svv-team/sortable)[ RSS](/packages/svv-team-sortable/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (3)Versions (39)Used By (0)

[![Build Status](https://camo.githubusercontent.com/9f203b11e8fcdb93e9c7cc8c5246af992b75075952238f4a18e69b8ce081dd4f/68747470733a2f2f7472617669732d63692e6f72672f626f7866726f6d6d6172732f7275746f72696b612d736f727461626c652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/boxfrommars/rutorika-sortable) [![Scrutinizer Code Quality](https://camo.githubusercontent.com/d8b015be50a3c0fccebdaa3ed92b1ce6d1e5a98379e0984a43abed50ceefc3e0/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f626f7866726f6d6d6172732f7275746f72696b612d736f727461626c652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/boxfrommars/rutorika-sortable/?branch=master) [![Latest Stable Version](https://camo.githubusercontent.com/325d216e2c8f2809f54cd748780da97887c7aa080be055819f61dbb4d9666fdf/68747470733a2f2f706f7365722e707567782e6f72672f7275746f72696b612f736f727461626c652f762f737461626c65)](https://packagist.org/packages/rutorika/sortable) [![Total Downloads](https://camo.githubusercontent.com/517d912627261a0c893f2ca6413841d05289373d38b8b3111a575d2303832f79/68747470733a2f2f706f7365722e707567782e6f72672f7275746f72696b612f736f727461626c652f646f776e6c6f616473)](https://packagist.org/packages/rutorika/sortable) [![Latest Unstable Version](https://camo.githubusercontent.com/5faad47dff075da5d731d354a1da7e4b64a210be541df0ac8e3ff21b85b9303a/68747470733a2f2f706f7365722e707567782e6f72672f7275746f72696b612f736f727461626c652f762f756e737461626c65)](https://packagist.org/packages/rutorika/sortable) [![License](https://camo.githubusercontent.com/1610ffbfac3aafa9b01914af22629bbd46b69d1fb7874bfef73f741bcaea58c8/68747470733a2f2f706f7365722e707567782e6f72672f7275746f72696b612f736f727461626c652f6c6963656e7365)](https://packagist.org/packages/rutorika/sortable)

Laravel 5 - Demo
----------------

[](#laravel-5---demo)

Install
-------

[](#install)

Install package through Composer

```
composer require rutorika/sortable
```

### Version Compatibility

[](#version-compatibility)

LaravelRutorika Sortable41.2.x (branch laravel4)&lt;=5.33.2.x5.43.4.x5.54.2.x5.74.7.x6.06.0.x7.x7.x.xSortable Trait
--------------

[](#sortable-trait)

Adds sortable behavior to Eloquent (Laravel) models

### Usage

[](#usage)

Add `position` field to your model (see below how to change this name):

```
// schema builder example
public function up()
{
    Schema::create('articles', function (Blueprint $table) {
        // ... other fields ...
        $table->integer('position'); // Your model must have position field:
    });
}
```

Add `\Rutorika\Sortable\SortableTrait` to your Eloquent model.

```
class Article extends Model
{
    use \Rutorika\Sortable\SortableTrait;
}
```

if you want to use custom column name for position, set `$sortableField`:

```
class Article extends Model
{
    use \Rutorika\Sortable\SortableTrait;

    protected static $sortableField = 'somefield';
}
```

Now you can move your entities with methods `moveBefore($entity)` and `moveAfter($entity)` (you dont need to save model after that, it has saved already):

```
$entity = Article::find(1);

$positionEntity = Article::find(10)

$entity->moveAfter($positionEntity);

// if $positionEntity->position is 14, then $entity->position is 15 now
```

Also this trait automatically defines entity position on the `create` event, so you do not need to add `position` manually, just create entities as usual:

```
$article = new Article();
$article->title = $faker->sentence(2);
$article->description = $faker->paragraph();
$article->save();
```

This entity will be at position `entitiesMaximumPosition + 1`

To get ordered entities use the `sorted` scope:

```
$articles = Article::sorted()->get();
```

> \*\* Note \*\*: Resorting does not take place after a record is deleted. Gaps in positional values do not affect the ordering of your lists. However, if you prefer to prevent gaps you can reposition your models using the `deleting` event. Something like:

```
// YourAppServiceProvider

YourModel::deleting(function ($model) {
    $model->next()->decrement('position');
});
```

> You need rutorika-sortable &gt;=2.3 to use `->next()`

### Sortable groups

[](#sortable-groups)

if you want group entity ordering by field, add to your model

```
protected static $sortableGroupField = 'fieldName';
```

now moving and ordering will be encapsulated by this field.

If you want group entity ordering by many fields, use as an array:

```
protected static $sortableGroupField = ['fieldName1','fieldName2'];
```

### Sortable many to many

[](#sortable-many-to-many)

Let's assume your database structure is

```
posts
    id
    title

tags
    id
    title

post_tag
    post_id
    tag_id

```

and you want to order *tags* for each *post*

Add `position` column to the pivot table (you can use any name you want, but `position` is used by default)

```
post_tag
    post_id
    tag_id
    position

```

Add `\Rutorika\Sortable\BelongsToSortedManyTrait` to your `Post` model and define `belongsToSortedMany` relation provided by this trait:

```
class Post extends Model {

    use BelongsToSortedManyTrait;

    public function tags()
    {
        return $this->belongsToSortedMany('\App\Tag');
    }
}
```

> Note: `$this->belongsToSortedMany` has different signature then `$this->belongsToMany` -- the second argument for this method is `$orderColumn` (`'position'` by default), next arguments are the same

Attaching tags to post with `save`/`sync`/`attach` methods will set proper position

```
    $post->tags()->save($tag) // or
    $post->tags()->attach($tag->id) // or
    $post->tags()->sync([$tagId1, $tagId2, /* ...tagIds */])
```

Getting related model is sorted by position

```
$post->tags; // ordered by position by default
```

You can reorder tags for given post

```
    $post->tags()->moveBefore($entityToMove, $whereToMoveEntity); // or
    $post->tags()->moveAfter($entityToMove, $whereToMoveEntity);
```

Many to many demo:  ([code](https://github.com/boxfrommars/rutorika-sortable-demo5))

You can also use polymorphic many to many relation with sortable behavour by using the `MorphsToSortedManyTrait` trait and returning `$this->morphToSortedMany()` from relation method.

By following the Laravel polymorphic many to many table relation your tables should look like

```
posts
    id
    title

tags
    id
    title

taggables
    tag_id
    position
    taggable_id
    taggable_type

```

And your model like

```
class Post extends Model {

    use MorphToSortedManyTrait;

    public function tags()
    {
        return $this->morphToSortedMany('\App\Tag', 'taggable');
    }
}
```

Sortable Controller
-------------------

[](#sortable-controller)

Also this package provides `\Rutorika\Sortable\SortableController`, which handle requests to sort entities

### Usage

[](#usage-1)

Add the service provider to `config/app.php`

```
'providers' => array(
    // providers...

    'Rutorika\Sortable\SortableServiceProvider',
)
```

publish the config:

```
php artisan vendor:publish
```

Add models you need to sort in the config `config/sortable.php`:

```
'entities' => array(
     'articles' => '\App\Article', // entityNameForUseInRequest => ModelName
     // or
     'articles' => ['entity' => '\App\Article'],
     // or for many to many
     'posts' => [
        'entity' => '\App\Post',
        'relation' => 'tags' // relation name (method name which returns $this->belongsToSortedMany)
     ]
),
```

Add route to the `sort` method of the controller:

```
Route::post('sort', '\Rutorika\Sortable\SortableController@sort');
```

Now if you post to this route valid data:

```
$validator = \Validator::make(\Input::all(), array(
    'type' => array('required', 'in:moveAfter,moveBefore'), // type of move, moveAfter or moveBefore
    'entityName' => array('required', 'in:' . implode(',', array_keys($sortableEntities))), // entity name, 'articles' in this example
    'positionEntityId' => 'required|numeric', // id of relative entity
    'id' => 'required|numeric', // entity id
));

// or for many to many

$validator = \Validator::make(\Input::all(), array(
    'type' => array('required', 'in:moveAfter,moveBefore'), // type of move, moveAfter or moveBefore
    'entityName' => array('required', 'in:' . implode(',', array_keys($sortableEntities))), // entity name, 'articles' in this example
    'positionEntityId' => 'required|numeric', // id of relative entity
    'id' => 'required|numeric', // entity id
    'parentId' => 'required|numeric', // parent entity id
));
```

Then entity with `\Input::get('id')` id will be moved relative by entity with `\Input::get('positionEntityId')` id.

For example, if request data is:

```
type:moveAfter
entityName:articles
id:3
positionEntityId:14

```

then the article with id 3 will be moved after the article with id 14.

### jQuery UI sortable example

[](#jquery-ui-sortable-example)

> Note: Laravel 5 has csrf middleware enabled by default, so you should setup ajax requests:

Template

```

    @foreach ($articles as $article)

        {{{ $article->id }}}
        {{{ $article->title }}}

    @endforeach

```

Template for many to many ordering

```

    @foreach ($post->tags as $tag)

        {{ $tag->id }}
        {{ $tag->title }}

    @endforeach

```

```
    /**
     *
     * @param type string 'insertAfter' or 'insertBefore'
     * @param entityName
     * @param id
     * @param positionId
     */
    var changePosition = function(requestData){
        $.ajax({
            'url': '/sort',
            'type': 'POST',
            'data': requestData,
            'success': function(data) {
                if (data.success) {
                    console.log('Saved!');
                } else {
                    console.error(data.errors);
                }
            },
            'error': function(){
                console.error('Something wrong!');
            }
        });
    };

    $(document).ready(function(){
        var $sortableTable = $('.sortable');
        if ($sortableTable.length > 0) {
            $sortableTable.sortable({
                handle: '.sortable-handle',
                axis: 'y',
                update: function(a, b){

                    var entityName = $(this).data('entityname');
                    var $sorted = b.item;

                    var $previous = $sorted.prev();
                    var $next = $sorted.next();

                    if ($previous.length > 0) {
                        changePosition({
                            parentId: $sorted.data('parentid'),
                            type: 'moveAfter',
                            entityName: entityName,
                            id: $sorted.data('itemid'),
                            positionEntityId: $previous.data('itemid')
                        });
                    } else if ($next.length > 0) {
                        changePosition({
                            parentId: $sorted.data('parentid'),
                            type: 'moveBefore',
                            entityName: entityName,
                            id: $sorted.data('itemid'),
                            positionEntityId: $next.data('itemid')
                        });
                    } else {
                        console.error('Something wrong!');
                    }
                },
                cursor: "move"
            });
        }
    });
```

Development
-----------

[](#development)

```
sudo docker build -t rutorika-sortable .
sudo docker run --volume $PWD:/project --rm --interactive --tty --user $(id -u):$(id -g) rutorika-sortable vendor/bin/phpunit

```

###  Health Score

29

—

LowBetter than 59% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity3

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity70

Established project with proven stability

 Bus Factor1

Top contributor holds 82.7% of commits — single point of failure

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 ~61 days

Recently: every ~118 days

Total

35

Last Release

2256d ago

Major Versions

1.2.6 → 2.32015-08-13

2.4.0 → 3.0.02015-12-19

3.5.0 → 4.02017-08-31

4.7.1 → 6.0.02019-09-16

6.0.0 → 7.0.02020-03-14

PHP version history (5 changes)0.9PHP &gt;=5.4.0

3.4.0PHP &gt;=5.6.4

4.0PHP &gt;=7

4.7PHP &gt;=7.1.3

7.0.0PHP &gt;=7.2.5

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/155924?v=4)[SVV](/maintainers/SVV)[@svv](https://github.com/svv)

---

Top Contributors

[![boxfrommars](https://avatars.githubusercontent.com/u/81930?v=4)](https://github.com/boxfrommars "boxfrommars (162 commits)")[![vluzrmos](https://avatars.githubusercontent.com/u/450848?v=4)](https://github.com/vluzrmos "vluzrmos (7 commits)")[![giordanolima](https://avatars.githubusercontent.com/u/8314190?v=4)](https://github.com/giordanolima "giordanolima (5 commits)")[![timothyasp](https://avatars.githubusercontent.com/u/707699?v=4)](https://github.com/timothyasp "timothyasp (4 commits)")[![mvrkljan](https://avatars.githubusercontent.com/u/694929?v=4)](https://github.com/mvrkljan "mvrkljan (4 commits)")[![Chrissi2812](https://avatars.githubusercontent.com/u/6141652?v=4)](https://github.com/Chrissi2812 "Chrissi2812 (4 commits)")[![dath](https://avatars.githubusercontent.com/u/2124173?v=4)](https://github.com/dath "dath (3 commits)")[![ZAZmaster](https://avatars.githubusercontent.com/u/7642406?v=4)](https://github.com/ZAZmaster "ZAZmaster (1 commits)")[![fabianmu](https://avatars.githubusercontent.com/u/89517?v=4)](https://github.com/fabianmu "fabianmu (1 commits)")[![scrutinizer-auto-fixer](https://avatars.githubusercontent.com/u/6253494?v=4)](https://github.com/scrutinizer-auto-fixer "scrutinizer-auto-fixer (1 commits)")[![SRWieZ](https://avatars.githubusercontent.com/u/1408020?v=4)](https://github.com/SRWieZ "SRWieZ (1 commits)")[![stevebauman](https://avatars.githubusercontent.com/u/6421846?v=4)](https://github.com/stevebauman "stevebauman (1 commits)")[![SVV-team](https://avatars.githubusercontent.com/u/48009651?v=4)](https://github.com/SVV-team "SVV-team (1 commits)")[![tonystatic](https://avatars.githubusercontent.com/u/5255487?v=4)](https://github.com/tonystatic "tonystatic (1 commits)")

---

Tags

laraveleloquentsortablesortlaravel5laravel4sortingorderorderingorderable

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[rutorika/sortable

Adds sortable behavior and ordering to Laravel Eloquent models. Grouping and many to many supported.

299992.5k14](/packages/rutorika-sortable)[spatie/eloquent-sortable

Sortable behaviour for eloquent models

1.5k22.9M268](/packages/spatie-eloquent-sortable)[jedrzej/pimpable

Laravel 4/5/6 package that allows to dynamically filter, sort and eager load relations for your models using request parameters

105179.0k1](/packages/jedrzej-pimpable)[jedrzej/sortable

Sortable trait for Laravel's Eloquent models - sort your models using request parameters

54261.0k1](/packages/jedrzej-sortable)[highsolutions/eloquent-sequence

A Laravel package for easy creation and management sequence support for Eloquent models with elastic configuration.

121130.3k](/packages/highsolutions-eloquent-sequence)[indexzer0/eloquent-filtering

Powerful eloquent filtering

22425.9k3](/packages/indexzer0-eloquent-filtering)

PHPackages © 2026

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