tijanidevit / query-filter
A simple, expressive, and powerful Laravel package that provides dynamic Eloquent models filters with clean syntax. It helps build reusable, maintainable, and readable query logic in Laravel apps.
Installs: 19
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 1
Forks: 0
Open Issues: 0
Type:package
pkg:composer/tijanidevit/query-filter
Requires (Dev)
- orchestra/testbench: 10.x-dev
README
A simple, expressive, and powerful Laravel package that provides dynamic Eloquent model filters with clean syntax. It helps you build reusable, maintainable, and readable query logic in Laravel applications.
Why Use This Package?
In many Laravel applications, especially admin dashboards, reporting systems, and search filters, developers often repeat the same filtering logic:
$query = User::query(); if (request()->filled('name')) { $query->where('name', request('name')); } if (request()->filled('status')) { $query->where('status', request('status')); } return $query->get();
With Query Filter, you can simplify this:
User::query() ->filterBy([ 'name' => request('name'), 'status' => request('status'), ]) ->get();
Installation
Run the composer command:
composer require tijanidevit/query-filter
The package supports auto-discovery. If you are using Laravel < 5.5, add the provider manually in config/app.php:
'providers' => [ Tijanidevit\QueryFilter\Providers\FilterProvider::class, ]
Available Filters
filterBy()
Filter by a column or multiple columns.
// Single column User::query()->filterBy('status', 'active')->get(); // Multiple columns User::query()->filterBy([ 'name' => 'Jane', 'status' => ['active', 'pending'], ])->get(); // Handle null values User::query()->filterBy([ 'email_verified_at' => ['null' => true], ])->get();
- Handles
null, arrays, or empty values smartly. - Fully chainable with other macros.
filterByRelation()
Filter using related models:
Post::query()->filterByRelation([ 'user' => [ 'status' => 'active', ] ])->get();
Supports:
- Closures for advanced queries
- Nullable checks (
['null' => true]) - Standard operators:
['operator', 'value']
filterWhereIn()
Flexible WHERE IN filtering for single or multiple columns.
// Single column with array User::query()->filterWhereIn('status', ['active', 'pending'])->get(); // Single column with multiple values as arguments User::query()->filterWhereIn('status', 'active', 'pending')->get(); // Single column with comma-separated string User::query()->filterWhereIn('status', 'active,pending')->get(); // Multiple columns with arrays User::query()->filterWhereIn([ 'status' => ['active', 'pending'], 'role' => ['admin', 'editor'] ])->get(); // Multiple columns with comma-separated strings User::query()->filterWhereIn([ 'status' => 'active,pending', 'role' => 'admin,editor' ])->get();
- Automatically converts comma-separated strings into arrays.
- Skips empty or null values.
- Fully chainable.
filterByMonth() / filterByYear()
Filter by month(s) or year(s):
Order::query() ->filterByMonth([1, 2]) // January and February ->filterByYear([2023, 2024]) ->get();
- Accepts single value or array of values.
- Uses app timezone or configurable timezone and converts to UTC for queries.
filterByDate()
Filter records by a single date:
User::query()->filterByDate('2024-01-01')->get();
- Converts to start and end of day automatically.
- Accepts optional timezone.
filterByDateRange()
Filter records between two dates:
Order::query()->filterByDateRange('2024-01-01', '2024-03-01')->get();
- Accepts optional timezone.
- Works with either
dateFrom,dateTo, or both.
filterFromRequest()
Automatically apply filters from request input:
User::query()->filterFromRequest(request(), [ 'name' => 'name', 'email' => 'email', 'status' => 'status', ])->get();
- Accepts an array where keys are database columns and values are request keys.
- Skips empty or missing request values.
sortResultBy(), latestBy(), oldestBy()
Sort results easily:
User::query()->sortResultBy('created_at', 'desc')->get(); Post::query()->latestBy('published_at')->get(); Post::query()->oldestBy('published_at')->get();
search() / orSearch() / searchByRelation()
Search for patterns in columns:
// Search single column User::query()->search('name', 'John')->get(); // Search multiple columns (OR) User::query()->orSearch(['name', 'email'], 'John')->get(); // Search in a related model Post::query()->searchByRelation('user', [ 'name' => 'John', ])->get();
- Default search uses SQL
LIKE %value%. - Supports relations, closures, and null checks.
Full Example
$users = User::query() ->filterBy([ 'name' => request('name'), 'status' => request('status'), 'email_verified_at' => ['null' => request('missing_email_verification')], ]) ->filterByRelation([ 'roles' => [ 'slug' => request('role_slug'), ], ]) ->filterWhereIn([ 'department' => request('departments'), // array or comma-separated 'status' => 'active,pending' ]) ->filterByDateRange(request('from'), request('to')) ->sortResultBy(request('sort_by'), request('sort_dir', 'asc')) ->get();
💡 Tips & Best Practices
Query Filter macros are designed to be fully chainable, letting you compose complex queries cleanly. Here are some recommended patterns:
1. Combine filterBy, filterWhereIn, and filterByRelation
$users = User::query() ->filterBy([ 'status' => request('status'), 'email_verified_at' => ['null' => request('missing_email_verification')], ]) ->filterWhereIn([ 'department' => request('departments'), // accepts array or comma-separated string 'role' => 'admin,editor' ]) ->filterByRelation([ 'manager' => [ 'status' => 'active', ], ]) ->get();
- Use
filterByfor simple columns with exact or nullable values. - Use
filterWhereInwhen you wantINfiltering, supporting arrays, comma-separated strings, or multiple arguments. - Use
filterByRelationto filter related models without manually writingwhereHasqueries.
2. Use filterByDate / filterByDateRange for date filtering
$orders = Order::query() ->filterByDate(request('date')) // exact day ->filterByDateRange(request('from'), request('to')) // range ->filterBy(['status' => request('status')]) ->get();
- Supports optional timezone.
- Automatically converts dates to start and end of day in UTC for consistency.
3. Search with search, orSearch, and searchByRelation
$posts = Post::query() ->search('title', request('title')) ->orSearch(['content', 'summary'], request('keyword')) ->searchByRelation('author', ['name' => request('author_name')]) ->get();
searchis for a single column.orSearchallows searching across multiple columns.searchByRelationsearches columns in related models.
4. Sorting and ordering
$users = User::query() ->filterBy(['status' => 'active']) ->sortResultBy(request('sort_by', 'created_at'), request('sort_dir', 'asc')) ->latestBy('last_login') ->get();
- Use
sortResultByfor dynamic column sorting. - Use
latestByoroldestByfor default chronological ordering.
5. Combining everything
For a full-featured admin or reporting query:
$users = User::query() ->filterBy([ 'status' => request('status'), 'email_verified_at' => ['null' => request('missing_email_verification')], ]) ->filterWhereIn([ 'department' => request('departments'), 'role' => 'admin,editor' ]) ->filterByRelation([ 'manager' => [ 'status' => 'active', ], ]) ->filterByDateRange(request('from'), request('to')) ->orSearch(['name', 'email'], request('search')) ->sortResultBy(request('sort_by', 'created_at'), request('sort_dir', 'asc')) ->latestBy('last_login') ->get();
- Keep your queries readable and maintainable by chaining macros instead of nesting raw
whereandorWherecalls. - The macros handle nulls, empty values, and type conversions, so your code stays clean.
Recommendations
- Always validate request inputs before passing to filters if needed.
- Use arrays or comma-separated strings with
filterWhereInfor maximum flexibility. - Combine macros in logical order:
filterBy→filterWhereIn→filterByRelation→filterByDate/DateRange→search→sort. - Leverage
filterFromRequestfor repetitive request-based filtering to simplify controllers.
This approach keeps your controllers slim and your queries consistent across the app.
---
## Requirements
- Laravel 9, 10, 11
- PHP 8.0+
---
## License
MIT © [Mustapha Tijani](mailto:thenewxpat@gmail.com)
---
## Contributing
Pull requests and issues are welcome. Help improve the package and make it more awesome!