Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/boxfrommars/rutorika-sortable
Adds sortable behavior to Laravel Eloquent models
https://github.com/boxfrommars/rutorika-sortable
laravel ordering php sortable sorting
Last synced: 26 days ago
JSON representation
Adds sortable behavior to Laravel Eloquent models
- Host: GitHub
- URL: https://github.com/boxfrommars/rutorika-sortable
- Owner: boxfrommars
- License: mit
- Created: 2014-06-27T23:06:57.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2024-03-20T11:03:18.000Z (8 months ago)
- Last Synced: 2024-05-22T04:04:19.185Z (6 months ago)
- Topics: laravel, ordering, php, sortable, sorting
- Language: PHP
- Homepage:
- Size: 192 KB
- Stars: 285
- Watchers: 6
- Forks: 51
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![Build Status](https://travis-ci.org/boxfrommars/rutorika-sortable.svg?branch=master)](https://travis-ci.org/boxfrommars/rutorika-sortable) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/boxfrommars/rutorika-sortable/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/boxfrommars/rutorika-sortable/?branch=master) [![Latest Stable Version](https://poser.pugx.org/rutorika/sortable/v/stable)](https://packagist.org/packages/rutorika/sortable) [![Total Downloads](https://poser.pugx.org/rutorika/sortable/downloads)](https://packagist.org/packages/rutorika/sortable) [![Latest Unstable Version](https://poser.pugx.org/rutorika/sortable/v/unstable)](https://packagist.org/packages/rutorika/sortable) [![License](https://poser.pugx.org/rutorika/sortable/license)](https://packagist.org/packages/rutorika/sortable)
## Laravel 5 - Demo
https://github.com/boxfrommars/rutorika-sortable-demo5
## Install
Install package through Composer
```bash
composer require rutorika/sortable
```
### Version CompatibilityLaravel | Rutorika Sortable
:----------------|:----------
4 | 1.2.x (branch laravel4)
<=5.3 | 3.2.x
5.4 | 3.4.x
5.5 | 4.2.x
5.7 | 4.7.x
6.0 | 6.0.x
7.x, 8.x | 8.x.x
9.x, 10.x, 11.x | 9.x.x## Sortable Trait
Adds sortable behavior to Eloquent (Laravel) models
### Usage
Add `position` field to your model (see below how to change this name):```php
// 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.
```php
class Article extends Model
{
use \Rutorika\Sortable\SortableTrait;
}
```if you want to use custom column name for position, set `$sortableField`:
```php
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):```php
$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:
```php
$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:
```php
$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:
```php
// YourAppServiceProviderYourModel::deleting(function ($model) {
$model->next()->decrement('position');
});
```
> You need rutorika-sortable >=2.3 to use `->next()`### Sortable groups
if you want group entity ordering by field, add to your model
```php
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:
```php
protected static $sortableGroupField = ['fieldName1','fieldName2'];
```### Sortable many to many
Let's assume your database structure is
```
posts
id
titletags
id
titlepost_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:
```php
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
```php
$post->tags()->save($tag) // or
$post->tags()->attach($tag->id) // or
$post->tags()->sync([$tagId1, $tagId2, /* ...tagIds */])
```Getting related model is sorted by position
```php
$post->tags; // ordered by position by default
```You can reorder tags for given post
```php
$post->tags()->moveBefore($entityToMove, $whereToMoveEntity); // or
$post->tags()->moveAfter($entityToMove, $whereToMoveEntity);
```Many to many demo: http://sortable5.boxfrommars.ru/posts ([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
titletags
id
titletaggables
tag_id
position
taggable_id
taggable_type
```And your model like
```php
class Post extends Model {use MorphToSortedManyTrait;
public function tags()
{
return $this->morphToSortedMany('\App\Tag', 'taggable');
}
}
```## Sortable Controller
Also this package provides `\Rutorika\Sortable\SortableController`, which handle requests to sort entities
### Usage
Add the service provider to `config/app.php````php
'providers' => array(
// providers...'Rutorika\Sortable\SortableServiceProvider',
)
```publish the config:
```bash
php artisan vendor:publish
```Add models you need to sort in the config `config/sortable.php`:
```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:
```php
Route::post('sort', '\Rutorika\Sortable\SortableController@sort');
```Now if you post to this route valid data:
```php
$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
> Note: Laravel 5 has csrf middleware enabled by default, so you should setup ajax requests: http://laravel.com/docs/5.0/routing#csrf-protection
Template
```html
@foreach ($articles as $article)
{{{ $article->id }}}
{{{ $article->title }}}
@endforeach
```
Template for many to many ordering
```html
@foreach ($post->tags as $tag)
{{ $tag->id }}
{{ $tag->title }}
@endforeach
```
```js
/**
*
* @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
```
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
```