laraditz/model-filter
Flexible Eloquent model filtering for Laravel with operator support (eq, gte, etc.), AND/OR grouping, and relationship filters via dot notation. Add a Filterable trait and allowlist fields, optionally create filter classes for custom logic, and filter using request params under filters[].
Installation:
composer require laraditz/model-filter
Apply Trait to Model:
Add Filterable trait to your Eloquent model and define $filterable array with allowed fields (including dot-notation for relationships):
use Laraditz\ModelFilter\Filterable;
class User extends Model
{
use Filterable;
protected array $filterable = [
'name',
'email',
'age',
'role.name', // Relationship field
];
First Use Case: Filter a query via HTTP request (e.g., API or form submission):
$users = User::filter(request()->all())->get();
Ensure request payload includes filters[] (e.g., {"filters[email]": "[email protected]"}).
php artisan make:filter UserFilter
$filterable allowlist and relationship definitions.filters[] is structured in incoming requests.Basic Filtering:
// In Controller/Service
$query = User::filter(request()->input('filters', []));
$results = $query->get();
Custom Filter Logic:
Extend generated filter class (app/Filters/UserFilter.php):
namespace App\Filters;
use Laraditz\ModelFilter\Filter;
class UserFilter extends Filter
{
public function isAdmin(): void
{
$this->builder->where('role.name', 'admin');
}
public function activeOnly(): void
{
$this->builder->where('is_active', true);
}
}
Apply in query:
$query = User::filter(request()->input('filters', []))
->when(request()->has('admin'), fn($q) => $q->isAdmin())
->when(request()->has('active'), fn($q) => $q->activeOnly());
Relationship Filtering:
Use dot-notation in $filterable (e.g., role.name) and pass filters like:
{
"filters[role.name]": "admin"
}
Operator Support:
Append operators to filter keys (e.g., filters[age][gt] for age > 25):
{
"filters[age][gt]": 25
}
Supported operators: =, !=, >, <, >=, <=, like, ilike.
request()->input('filters', []) to capture filter parameters.filters[] in a FormRequest class:
public function rules(): array
{
return [
'filters.name' => 'sometimes|string',
'filters.email' => 'sometimes|email',
];
}
$users = User::filter(request()->input('filters', []))
->paginate(10);
return new UserResource(User::filter(request()->input('filters', []))->get());
Namespace Change (v2):
filters[] in the request payload.{"email": "[email protected]"} → New: {"filters[email]": "[email protected]"}.Strict Allowlist:
$filterable are allowed. Omitting a field silently ignores it (no error).request()->input('filters', []) to verify payload structure.Relationship Pitfalls:
role()) are defined in the model.role.name) requires the relationship (role) and field (name) to exist.Operator Conflicts:
filters[age][gt] and filters[age][lt] in the same request if not handled by the package (may require custom logic).Query Inspection:
Use toSql() and getBindings() to debug generated queries:
$query = User::filter(request()->input('filters', []));
dd($query->toSql(), $query->getBindings());
Filter Validation: Temporarily log filter inputs:
\Log::info('Raw filters:', request()->input('filters', []));
Custom Filter Issues:
Ensure custom filter methods in UserFilter are public and follow the void return type convention.
Custom Operators:
Extend the package by publishing and modifying the operator logic (check vendor/laraditz/model-filter/src/Operators/).
Filter Events: Listen for filter application via events (if the package emits them; check source for hooks).
Dynamic Allowlists:
Override $filterable dynamically (e.g., based on user roles):
protected array $filterable = [];
public function boot()
{
$this->filterable = auth()->user()->can('admin') ? ['*'] : ['name', 'email'];
}
Caching Filters: Cache filtered query results if filters are static (e.g., dashboard widgets):
$cacheKey = 'users_filtered_' . md5(serialize(request()->input('filters', [])));
return Cache::remember($cacheKey, now()->addHours(1), function() {
return User::filter(request()->input('filters', []))->get();
});
How can I help you explore Laravel packages today?