esign / laravel-query-filters
Apply filters to Laravel's query builder.
Installs: 3 373
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 3
Forks: 0
Open Issues: 0
Requires
- php: ^8.0
- illuminate/console: ^8.0|^9.0|^10.0|^11.0
- illuminate/database: ^8.0|^9.0|^10.0|^11.0
- illuminate/pipeline: ^8.0|^9.0|^10.0|^11.0
- illuminate/support: ^8.0|^9.0|^10.0|^11.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.5
- orchestra/testbench: ^6.0|^7.0|^8.0|^9.0
- phpunit/phpunit: ^9.0|^10.0
This package is auto-updated.
Last update: 2024-10-12 22:18:08 UTC
README
This package allows you to easily apply filters to Laravel's query builder by abstracting filter logic into dedicated classes.
Installation
You can install the package via composer:
composer require esign/laravel-query-filters
The package will automatically register a service provider.
Usage
Preparing your model
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; }
Applying filters
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();
Defining default filters
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();
Creating filters
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); } }
Method filters
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.
Testing
composer test
License
The MIT License (MIT). Please see License File for more information.