Installation:
composer require heroicpixels/filterable
Register the service provider in config/app.php:
'providers' => [
// ...
Heroicpixels\Filterable\FilterableServiceProvider::class,
],
First Use Case:
Apply the trait to an Eloquent model (e.g., User.php):
use Heroicpixels\Filterable\FilterableTrait;
class User extends Model
{
use FilterableTrait;
protected $filterable = ['name', 'email', 'status'];
}
Now, a request to /users?name=John will automatically filter results where name = 'John'.
$filterable array in your model to define which columns can be filtered.Request query parameters, so no manual parsing is needed.= by default for equality checks (e.g., ?status=active).Define Filterable Columns:
protected $filterable = ['column1', 'column2', 'status'];
Query Integration:
$users = User::filterable()->get(); // Applies URL filters
WHERE clauses based on query params (e.g., ?status=active).Customizing Behavior:
$filterable:
protected $filterable = [
'status' => ['operator' => 'like'],
'created_at' => ['operator' => '>'],
];
?status[]=active&status[]=pending for IN clauses.Wrapper Class:
For non-Eloquent queries, use FilterableWrapper:
$results = (new FilterableWrapper(User::query()))
->filterable()
->get();
Route::middleware('throttle') for filtered endpoints (e.g., /api/users?status=active).Cache::remember to cache filtered results:
Cache::remember("users_{$request->query()}", now()->addHours(1), function () {
return User::filterable()->get();
});
Request in tests:
$request = Request::create('/users', 'GET', ['status' => 'active']);
$this->app->instance('request', $request);
SQL Injection:
?status[operator]=DROP TABLE). Validate operators in $filterable:
protected $filterable = [
'status' => ['operator' => 'in'], // Explicitly restrict
];
Case Sensitivity:
protected $filterable = [
'name' => ['operator' => 'like', 'modifier' => 'LOWER'],
];
Boolean Fields:
1/0 or true/false in queries (e.g., ?is_active=1). Avoid ?is_active=true unless configured.Performance:
->select() to limit columns:
User::filterable()->select('id', 'name')->get();
Log Queries:
Enable Laravel’s query logging in .env:
DB_LOG_QUERIES=true
Check storage/logs/laravel.log for generated SQL.
Validate Filters:
dd($this->getFilterableQuery()) to your model’s filterable() method to inspect parsed filters.Operator Mismatches:
$filterable match the query (e.g., ?price__gt=100 requires operator: '>').Custom Operators:
Extend Heroicpixels\Filterable\Operators\OperatorResolver to add custom logic (e.g., contains for partial matches).
Pre-Filter Hooks:
Override getFilterableQuery() in your model to modify filters before execution:
protected function getFilterableQuery()
{
$query = parent::getFilterableQuery();
$query->where('deleted_at', null); // Add soft-deletes
return $query;
}
Non-Standard Requests:
For API tokens or non-Request inputs, bind the package’s Filterable class manually:
$filterable = app('filterable');
$filterable->setRequest($customRequest);
Localization:
Override operator symbols for non-English apps (e.g., > → > in Spanish, but ensure consistency in $filterable).
How can I help you explore Laravel packages today?