Skip to content

Instantly share code, notes, and snippets.

@patoui
Last active February 21, 2023 09:02
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save patoui/9571c3a03a6008852ea9705a80a69aab to your computer and use it in GitHub Desktop.
Save patoui/9571c3a03a6008852ea9705a80a69aab to your computer and use it in GitHub Desktop.
## Introduction
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())
```
### Sortable trait
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;
}
}
```
### Model setup
The model setup requires 2 things:
1. Add a `use Sortable;` statement (and import the class `use App\Sortable` as seen in the example below)
2. Add a `sortable` public property which is an array of values that may be sorted
Example 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'];
}
```
### Trait usage
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()`
### Extra
If you want to see this in action, I've created a small Laravel application to demo it.
[Sortable Demo](https://github.com/patoui/sortable-demo)
Demo setup steps are as follows:
1. Clone repository `git clone https://github.com/patoui/sortable-demo.git`
2. Composer install `composer install`
3. Run migrations `php artisan migrate`
4. Run seeders `php artisan db:seed`
5. Run artisan serv `php artisan serve`
6. Visit `127.0.0.1:8000` (or value displayed from artisan serve)
## Conclusion
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!
### Resources
* [Laravel Query Scopes - Local Scopes](https://laravel.com/docs/5.5/eloquent#local-scopes)
### Gist
* https://gist.github.com/patoui/9571c3a03a6008852ea9705a80a69aab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment