This package allows you to easily apply filters to Laravel's query builder by abstracting filter logic into dedicated classes.
You can install the package via composer:
composer require esign/laravel-query-filters
The package will automatically register a service provider.
To apply filters to your model you may use the Esign\QueryFilters\Concerns\Filterable
trait:
use Esign\QueryFilters\Concerns\Filterable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Filterable;
}
After applying the trait to your model, a query scope filter
will be available, that accepts an array of possible filters:
use App\Models\Filters\TitleFilter;
use App\Models\Filters\BodyFilter;
Post::filter([
TitleFilter::class,
BodyFilter::class,
])->get();
The filter
scope will send the query builder through an array of filters.
To pass the query builder to the next filter, you should call the $next
callback with the $query
.
You're not limited to only using string based classes as filters, you can pass actual instances, callbacks, or pass parameters along with your class based string:
use App\Models\Filters\TitleFilter;
use Closure;
use Illuminate\Database\Eloquent\Builder;
Post::filter([
// Class strings
TitleFilter::class,
// Class strings that pass a parameter to the handle method
TitleFilter::class . ':dogs',
// Class instance with a constructor parameter
new TitleFilter('dogs'),
// Use a callback
function (Builder $query, Closure $next): Builder {
$query->where('title', 'like', '%dogs%');
return $next($query);
},
])->get();
In case you do not provide an array of filter items, you may define a set of default filters on your model:
use App\Models\Filters\TitleFilter;
use Esign\QueryFilters\Concerns\Filterable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Filterable;
public function getFilters(): array
{
return [
TitleFilter::class,
];
}
}
You may now call the filter
scope without passing an array:
Post::filter()->get();
To create a filter class you may use the make:filter
Artisan command:
php artisan make:filter TitleFilter
namespace App\Models\Filters;
use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
class TitleFilter
{
public function __construct(protected Request $request)
{}
public function handle(Builder $query, Closure $next): Builder
{
$query->where('title', 'like', '%' . $this->request->query('search') . '%');
return $next($query);
}
}
This package also ships with a handy MethodFilter
class that allows you to define filters for query string parameters as methods.
Imagine we have a request that filters a list of posts with the following query string: ?published_at=2022-01-01&title=dogs
.
We could create a PostFilter
that extends the MethodFilter
class with the camelcased method names:
use Esign\QueryFilters\Filters\MethodFilter;
use Illuminate\Database\Eloquent\Builder;
class PostFilter extends MethodFilter
{
public function title(mixed $value): Builder
{
return $this->query->where('title', 'like', "%$value%");
}
public function publishedAt(mixed $value): Builder
{
return $this->query->where('published_at', '=', $value);
}
}
By default, query string parameters that contain an empty value won't be called.
composer test
The MIT License (MIT). Please see License File for more information.