arneetsingh / laravel-customsort
A package to manually sort records of a eloquent model in custom order
Requires
- php: ^8.1
- illuminate/contracts: ^9.0
- spatie/laravel-package-tools: ^1.9.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.8
- nunomaduro/collision: ^6.0
- orchestra/testbench: ^7.0
- phpunit/phpunit: ^9.5
- spatie/laravel-ray: ^1.26
This package is auto-updated.
Last update: 2024-06-09 06:03:03 UTC
README
Problem it solves:
Say there is a need to show certain records of posts, eg. featured posts on top in your listing page. Just a custom order set by user to show specific posts in a specific order on top.
Installation
You can install the package via composer:
composer require arneetsingh/laravel-customsort
Publish and run the migrations with:
php artisan vendor:publish --tag="laravel-customsort-migrations"
php artisan migrate
You can publish the config file with:
php artisan vendor:publish --tag="laravel-customsort-config"
Usage
Model
Use the CanCustomSort
trait in your model you want to have the ability of sorting manually.
<?php namespace App\Models; use ArneetSingh\CustomSort\Traits\CanCustomSort; use Illuminate\Database\Eloquent\Model; class Post extends Model { use CanCustomSort; }
Setting the order
Lets say we have 5 posts in our Post model. and we want to set them in order of ids - 2,4,1,5,3
Post::setNewOrder([2, 4, 1, 5, 3]);
Do note you don't need to pass all of your posts, you can though. Just the ones passed will be returned on top in that order.
Fetching in Custom Order
Post::orderByCustom()->get();
Will return post in order set first, and then rest of posts.
Set Priority per model basis
$post->setOrderPriority(10);
If the priority no is higher than other posts, it will be moved to top in results.
Example
Lets say we have 5 posts in our Post model. and we want to set them in order of ids - 2,4,1,5,3
Request: PUT Endpoint: /posts/customSort Payload: { "custom_sort":[ { "id":2, "priority":5 }, { "id":4, "priority":4 }, { "id":1, "priority":3 }, { "id":5, "priority":2 }, { "id":3, "priority":1 } ] }
Controller code could look like
public function store(Request $request) { $request->validate([ 'custom_sort' => 'required', 'custom_sort.*.id' => "required|exists:posts,id", 'custom_sort.*.priority' => 'required|integer' ]); $morphClass = (new Post())->customSort()->getMorphClass(); collect($request->custom_sort)->transform(function ($item) use($morphClass) { CustomSort::create([ 'sortable_id' => $item['id'], 'sortable_type' => $morphClass, 'priority' => $item['priority'] ]); }); }
Frontend Tips
I used SortabelJS for having the ability to drag and drop to set manual order. And here is snippet to javascript code.
let posts = [] // SortableJS onEnd handler would look like this onEnd: function ({ oldIndex, newIndex }){ const movedItem = posts.splice(oldIndex, 1)[0] posts.splice(newIndex, 0, movedItem) } // prepare payload preparePayload: function() { const order = posts.map((item, key) => { return { id: item.id, priority: posts.length - key } }) return { custom_sort: order } }
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.