abdrzakoxa / laravel-eloquent-filter
Scalable way to filter laravel model
Requires
- php: ^7.3|^8.0
- illuminate/database: ^6.0|^7.0|^8.0|^9.0
- illuminate/support: ^6.0|^7.0|^8.0|^9.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.19
- orchestra/testbench: ^5.0|^6.0
- phpunit/phpunit: ^9.4
This package is auto-updated.
Last update: 2025-04-21 10:43:19 UTC
README
Laravel Eloquent Filter
Introduction
Lets say we want to return a list of users filtered by multiple parameters. When we navigate to:
/users?name=avf&roles[]=admin&roles[]=manager&roles[]=client&limit=10
$request->all()
will return:
['name' => 'avf', 'roles' => ['admin', 'manager', 'client'], 'limit' => '10']
To filter by all those parameters we would need to do something like:
<?php namespace App\Http\Controllers; use App\Models\User; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; class UserController extends Controller { public function index(Request $request) { $query = User::query(); $query->when($request->has('name'), function (Builder $builder) use ($request) { $builder->where('name', 'LIKE', '%'.$request->input('name').'%'); }); if (auth()->user()->isAdmin()) { $allowedRoles = ['admin', 'manager', 'client']; } elseif (auth()->user()->isManager()) { $allowedRoles = ['client']; } else { $allowedRoles = []; } $roles = []; foreach ((array) $request->input('roles') as $role) { if (in_array($role, $allowedRoles, true)) { $roles[] = $role; } } $query->whereHas('roles', function ($q) use ($roles) { return $q->whereIn('name', $roles); }); if ($request->has('limit') && is_numeric($request->input('limit')) && $request->input('limit') < 100) { $limit = (int) $request->input('limit'); } else { $limit = 10; } $query->limit($limit); return $query->get(); } }
To filter that same input With Eloquent Filters:
<?php namespace App\Http\Controllers; use App\Models\User; use Illuminate\Http\Request; class UserController extends Controller { public function index(Request $request) { return User::filter($request->all())->get(); } }
Installation
composer require abdrzakoxa/laravel-eloquent-filter
Usage
Create your custom filter
create app/EloquentFilters/NameFilter.php
file
<?php namespace App\EloquentFilters; use Illuminate\Database\Eloquent\Builder; class NameFilter { /** * Apply the filter after validation passes & sanitize * @param string $value * @param Builder $builder */ public function handle(string $value, Builder $builder): void { $builder->where('name', $value); } /** * @param mixed $value * @return mixed */ public function sanitize($value) { return is_string($value) ? $value : ''; } /** * @param mixed $value * @return bool|string|array */ public function validate($value) { return strlen($value) > 5 && strlen($value) < 100; } }
Also, you can use only handle method
Apply NameFilter to a model
<?php namespace App\Models; use App\EloquentFilters\NameFilter; use Abdrzakoxa\EloquentFilter\Traits\Filterable; use Illuminate\Database\Eloquent\Model; class User extends Model { use Filterable; protected $filters = [ NameFilter::class, ]; }
Available Filters
The following filters are available out of the box:
BetweenFilter
usage:
BetweenFilter
is an available filter to filter between two dates
/users?approved_between[]=2020-10-03&approved_between[]=2020-11-03&created_between[]=2020-09-01&created_between[]=2020-12-01
// ... use Abdrzakoxa\EloquentFilter\Traits\Filterable; use Abdrzakoxa\EloquentFilter\Filters\BetweenFilter; class User extends Model { use Filterable; protected $filters = [ BetweenFilter::class . ':approved_at' => 'approved_between', BetweenFilter::class => 'created_between', ]; }
User::filter($request->all())->get();
LimitFilter
usage:
LimitFilter
is an available filter to limit the final result
/users?limit=10
// ... use Abdrzakoxa\EloquentFilter\Traits\Filterable; use Abdrzakoxa\EloquentFilter\Filters\LimitFilter; class User extends Model { use Filterable; protected $filters = [ LimitFilter::class ]; }
User::filter($request->all())->get();
SortingFilter
usage:
LimitFilter
is an available filter to sort the final result
/users?sorting=asc
// ... use Abdrzakoxa\EloquentFilter\Traits\Filterable; use Abdrzakoxa\EloquentFilter\Filters\SortingFilter; class User extends Model { use Filterable; protected $filters = [ SortingFilter::class . ':approved_at' // sorting by approved_at column ]; }
User::filter($request->all())->get();
Contributing
Any contributions welcome!