oooiik/laravel-query-filter
Composer 安装命令:
composer require oooiik/laravel-query-filter
包简介
A clean, convention-based way to extract Eloquent query filters into dedicated filter classes — keep your controllers and scopes thin.
README 文档
README
A clean, convention-based way to extract Eloquent query filters into dedicated filter classes. Keep your controllers thin, your scopes focused, and your filtering logic testable.
// Before — filtering logic leaking into the controller $users = User::query() ->when($request->username, fn($q, $v) => $q->where('username', $v)) ->when($request->role, fn($q, $v) => $q->whereHas('role', fn($r) => $r->where('title', $v))) ->when($request->created_after, fn($q, $v) => $q->where('created_at', '>=', $v)) ->paginate(); // After — one line, all filtering in UserFilter $users = User::filter($request->validated())->paginate();
Features
- 🎯 Convention over configuration — each public method on your filter class becomes a filter key. No registration, no metadata.
- 🪶 Single trait + base class — add
Filterableto a model, point it at a filter class, done. - 🛠 Artisan generator —
php artisan make:filter UserFilterscaffolds the class for you. - 🔁 Composable — apply multiple parameter sets to the same filter instance and chain into the query.
- ⚙️ Defaults & fallbacks — provide default parameter values and fallback handlers for missing keys.
- 🧩 Laravel 6 → 12 — broad compatibility, PHP 7.3+ through 8.x.
Installation
composer require oooiik/laravel-query-filter
The service provider is auto-registered via Laravel's package discovery.
Quick Start
1. Generate a filter
php artisan make:filter UserFilter
This creates app/Filters/UserFilter.php.
2. Define your filter methods
Each public method becomes a filter key matching its name:
namespace App\Filters; use Oooiik\LaravelQueryFilter\Filters\QueryFilter; class UserFilter extends QueryFilter { public function username($username) { $this->builder->where('username', $username); } public function role($role) { $this->builder->whereHas('role', function ($query) use ($role) { $query->where('title', $role); }); } public function createdAfter($date) { $this->builder->where('created_at', '>=', $date); } }
3. Attach the filter to your model
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Oooiik\LaravelQueryFilter\Traits\Model\Filterable; use App\Filters\UserFilter; class User extends Model { use Filterable; protected $defaultFilter = UserFilter::class; }
4. Use it
// Controller public function index(Request $request) { $validated = $request->validate([ 'username' => 'nullable|string', 'role' => 'nullable|string', 'createdAfter' => 'nullable|date', ]); return User::filter($validated)->paginate(); }
Missing keys are silently ignored — only the filter methods that match input parameters run.
Advanced Usage
Default parameters
Use the $default property to pre-fill values when a key is missing from the input:
class UserFilter extends QueryFilter { public $default = [ 'status' => 'active', 'sort' => 'created_at', ]; public function status($status) { $this->builder->where('status', $status); } public function sort($column) { $this->builder->orderBy($column, 'desc'); } }
Calling User::filter([]) will still apply status = active and sort by created_at desc.
Fallback methods
Use $fallback to redirect missing input keys to a different method:
class UserFilter extends QueryFilter { public $fallback = [ 'search' => 'searchByName', ]; public function searchByName($value) { $this->builder->where('name', 'like', "%{$value}%"); } }
If the search key is missing from input, searchByName runs with whatever value was provided as the fallback source.
Standalone filter instance (chaining)
Apply multiple parameter sets to the same filter:
$filter = User::createFilter(UserFilter::class); $filter->apply(['role' => 'admin']); $filter->apply(['status' => 'active']); $query = $filter->query(); // Both filter sets are now applied to the builder
Accessing all parameters
Filter methods receive the full parameter array as a second argument:
public function username($username, $allParams) { if (! empty($allParams['exact_match'])) { $this->builder->where('username', $username); } else { $this->builder->where('username', 'like', "%{$username}%"); } }
Comparison with spatie/laravel-query-builder
laravel-query-filter |
spatie/laravel-query-builder |
|
|---|---|---|
| Approach | Convention-based — method = filter key | Declarative — register allowed filters explicitly |
| Per-model class | Yes, dedicated filter class | Optional, often inline |
| Custom filter logic | Plain PHP method | AllowedFilter::callback() |
| Best for | Complex filtering with reusable logic | API endpoints with simple filtering needs |
Both are great — choose laravel-query-filter when you want a dedicated class per model with reusable, testable filter logic.
Requirements
- PHP 7.3 or higher
- Laravel 6.x — 12.x
Compatibility Matrix
| Laravel | PHP | Status |
|---|---|---|
| 12.x | 8.2+ | ✅ Supported |
| 11.x | 8.2+ | ✅ Supported |
| 10.x | 8.1+ | ✅ Supported |
| 9.x | 8.0+ | ✅ Supported |
| 8.x | 7.3+ | ✅ Supported |
| 7.x | 7.3+ | ✅ Supported |
| 6.x | 7.3+ | ✅ Supported |
Contributing
Pull requests are welcome. For substantial changes, please open an issue first to discuss the direction.
Bug reports and feature ideas → GitHub Issues.
Credits
- Obidjon Toshev — author & maintainer
- All contributors
License
The MIT License (MIT). See LICENSE for details.
统计信息
- 总下载量: 1.14k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 8
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2022-10-27