lacodix/laravel-model-filter
Filter, search, and sort Eloquent models with reusable filter classes and query-string support. Includes built-in types (string, date, number, enum), relation/nested relation filtering, custom complex logic, and filter visualisation.
This package, Laravel Model Filter, simplifies filtering Eloquent models with a fluent, chainable API. To start, install via Composer:
composer require lacodix/laravel-model-filter
Publish the config (optional):
php artisan vendor:publish --provider="Lacodix\LaravelModelFilter\LaravelModelFilterServiceProvider"
Basic usage:
use Lacodix\LaravelModelFilter\Filter;
$filtered = Model::filter(Filter::where('active', true)->orWhere('name', 'like', '%test%'));
For the new belongstomanytimeframe feature (v4.4.1+), initialize with:
$filtered = Model::filter(Filter::belongstomanytimeframe('posts', 'created_at', 'week'));
$filter = Filter::where('status', 'published');
Model::filter($filter);
$filter = Filter::where('price', '>', 100)
->where('category', 'in', ['electronics', 'books'])
->orWhere('is_featured', true);
$filter = Filter::whereHas('author', fn($q) => $q->where('active', true));
Use the belongstomanytimeframe method to filter pivot relationships by time ranges (e.g., day, week, month):
// Filter posts created in the last week for a user
$filter = Filter::belongstomanytimeframe('posts', 'created_at', 'week');
User::filter($filter)->get();
Supported Modes:
day, week, month, quarter, year, or custom Carbon intervals.return UserResource::collection(User::filter($filter)->get());
Cache::remember("filtered_{$filter->hash()}", now()->addHours(1), fn() =>
Model::filter($filter)->get()
);
belongstomanytimeframe) use the system timezone by default. Explicitly set timezone in queries if needed:
$filter->setTimezone('America/New_York');
belongstomanytimeframe, ensure the pivot table’s timestamp column (e.g., created_at) matches the field name in the method call. Misalignment throws SyntaxError.whereHas/orWhereHas with timeframe filters—use raw SQL or subqueries for complex cases:
$filter->whereRaw('EXISTS (
SELECT 1 FROM post_user WHERE users.id = user_id
AND posts.created_at > NOW() - INTERVAL 1 WEEK
)');
$filter->hash() to debug cached or repeated queries. Identical filters produce the same hash.\DB::enableQueryLog();
Model::filter($filter)->get();
dd(\DB::getQueryLog());
// config/laravel-model-filter.php
'timeframes' => [
'custom' => 'custom_interval',
],
Then implement custom_interval in a service provider.setPivotColumns() method:
$filter->belongstomanytimeframe('posts', 'published_at', 'month')
->setPivotColumns(['user_id', 'post_id', 'custom_timestamp']);
Model::macro('filterByRole', function ($role) {
return $this->filter(Filter::whereHas('roles', fn($q) => $q->where('name', $role)));
});
config/laravel-model-filter.php:
'timezone' => 'UTC',
'strict' => env('FILTER_STRICT', false),
withTrashed() for inclusive filtering:
Model::withTrashed()->filter($filter)->get();
$filter = Filter::buildFromRequest(request()->all());
$filter = \Mockery::mock(Filter::class);
$filter->shouldReceive('apply')->andReturn($query);
How can I help you explore Laravel packages today?