indexzer0/eloquent-filtering
Define allowed filters on your Eloquent models and apply them from simple arrays or request data—no custom query logic. Supports complex, type-based filtering for APIs and dashboards on Laravel 10+ / PHP 8.2+.
Install the package:
composer require indexzer0/eloquent-filtering
php artisan eloquent-filtering:install
Implement IsFilterable in your model:
use IndexZer0\EloquentFiltering\Contracts\IsFilterable;
use IndexZer0\EloquentFiltering\Traits\Filterable;
class Product extends Model implements IsFilterable
{
use Filterable;
public function allowedFilters(): AllowedFilterList
{
return Filter::only(
Filter::field('name', [FilterType::EQUAL])
);
}
}
First API request usage:
$products = Product::filter([
[
'target' => 'name',
'type' => '$eq',
'value' => 'TV'
]
])->get();
allowedFilters() method for filter configurations.API Controller Integration:
public function index(Request $request)
{
$filters = $request->input('filters', []);
$products = Product::filter($filters)->paginate(10);
return response()->json($products);
}
Dynamic Filtering with Relationships:
public function allowedFilters(): AllowedFilterList
{
return Filter::only(
Filter::field('name', [FilterType::EQUAL]),
Filter::field('category.name', [FilterType::EQUAL]) // Nested relationship
);
}
Combining Filters with Conditions:
$filters = [
[
'type' => '$or',
'filters' => [
['target' => 'name', 'type' => '$eq', 'value' => 'TV'],
['target' => 'price', 'type' => '$gt', 'value' => 100]
]
]
];
Validation Layer:
use IndexZer0\EloquentFiltering\Validation\FilterValidator;
public function index(Request $request)
{
$validator = FilterValidator::make($request->input('filters'));
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
// Proceed with filtering
}
FormRequest to validate and sanitize filter inputs.$products = Cache::remember("products_{$filterHash}", now()->addHours(1), function () use ($filters) {
return Product::filter($filters)->get();
});
$this->get('/products?filters[0][target]=name&filters[0][type]=$eq&filters[0][value]=TV');
Performance:
->select() to limit columns if full model hydration isn't needed.JSON Path Wildcards:
json_length) for JSON path filters.->toSql() to verify generated queries.Sorting Limitation:
->orderBy() for critical projects.Condition Filters:
$or/$and are always allowed but may require explicit definition for clarity.$query = Product::filter($filters);
dd($query->toSql(), $query->getBindings());
FilterValidator for unsupported filter types or targets.Custom Filter Types:
Filter::custom('custom_filter', function ($query, $value) {
return $query->where('column', 'like', "%{$value}%");
});
Filter Modifiers:
Extend FilterModifier to add logic like case-insensitive matching:
Filter::field('name', [FilterType::EQUAL])
->modifyWith('lowercase', fn ($value) => strtolower($value));
Global Filter Configuration:
Override defaults in config/eloquent-filtering.php:
'default_modifiers' => [
'trim' => fn ($value) => trim($value),
],
Filter::group('search', ...)).allowedFilters() includes soft-deleted columns if needed:
Filter::field('deleted_at', [FilterType::EQUAL])->when(fn () => auth()->check());
How can I help you explore Laravel packages today?