Patrique Ouimet
Senior Product Engineer
Sat, Sep 16, 2017 5:06 PM
This post aims to provide a simple example of how to use traits with Laravel Query Scopes. The trait will sort columns based on "sort" and "direction" being found within the request, while protecting the database of unwanted sorting by adding a "sortables" property to the model. The end result looks like this with a Post model as an example:
Post::sort(request())
Create the trait below in the "App" namespace (or change the namespace to suit your projects convention).
<?php
namespace App;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
trait Sortable
{
/**
* Scope a query to sort results.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeSort(Builder $query, Request $request)
{
// Get sortable column
$sortables = data_get($this, 'sortables', []);
// Get the column to sort
$sort = $request->get('sort');
// Get the direction of which to sort
$direction = $request->get('direction', 'desc');
// Ensure column to sort is part of model's sortables property
// and that the direction is a valid value
if ($sort
&& in_array($sort, $sortables)
&& $direction
&& in_array($direction, ['asc', 'desc'])) {
// Return ordered query
return $query->orderBy($sort, $direction);
}
// No sorting, return query
return $query;
}
}
The model setup requires 2 things:
use Sortable;
statement (and import the class use App\Sortable
as seen in the example below)sortable
public property which is an array of values that may be sortedExample below allows sorting for the columns: id, views, published_at
<?php
namespace App;
use App\Sortable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Sortable;
public $sortables = ['id', 'views', 'published_at'];
}
Below is an example of the usage of the sortable trait (query scope).
<?php
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
return Post::sort(request())->get();
}
}
NOTE: This also works with pagination Post::sort(request())->paginate()
If you want to see this in action, I've created a small Laravel application to demo it.
Demo setup steps are as follows:
git clone https://github.com/patoui/sortable-demo.git
composer install
php artisan migrate
php artisan db:seed
php artisan serve
127.0.0.1:8000
(or value displayed from artisan serve)That's it! I believe it's a pretty straight forward approach and made easy by Laravel's Query Scopes. Query Scopes are something I had avoided in my early Laravel development days, but I've learnt to embrace the simplicity that Laravel brings to complex situations and it's been enlightening. I suggest to everyone who's using Laravel to dig deep into the framework, there's TONS of hidden gems in there to make your life easier. Thank you Taylor Otwell and all the contributors for making my development life easier.
Hope you liked my article, please leave comments and share if you like!