abbasudo/laravel-purity
Laravel Purity adds elegant filtering and sorting to Eloquent queries. Just call filter() on a model query, then let clients apply complex conditions via URL query parameters (e.g., filters[title][$contains]=...). Great for clean, flexible APIs.
Installation:
composer require abbasudo/laravel-purity
Publish the config (optional):
php artisan vendor:publish --provider="Abbasudo\Purity\PurityServiceProvider"
First Use Case:
Add filter() to any Eloquent query:
$posts = Post::filter()->get();
Now, clients can filter via URL params like:
GET /posts?filters[title][$contains]=Laravel
Key Files to Review:
config/purity.php (for global settings like allowed fields)app/Models/Post.php (to define custom filters if needed)Basic Filtering:
// Controller
public function index()
{
return Post::filter()->get();
}
URL: /posts?filters[title][$contains]=search-term
Restricting Fields: Define allowed fields in the model or config:
// Model
protected $filterable = ['title', 'published_at', 'author.name'];
// OR in config/purity.php
'allowed_fields' => ['title', 'published_at'],
Custom Filters: Extend the package’s filter logic:
use Abbasudo\Purity\Filters\Filter;
class CustomFilter extends Filter
{
public function apply($query, $value)
{
return $query->where('custom_column', $value);
}
}
Register in config/purity.php:
'filters' => [
'custom' => \App\Filters\CustomFilter::class,
],
Sorting:
Post::filter()->sort()->get();
URL: /posts?sort=-created_at
Livewire Integration:
use Abbasudo\Purity\Livewire\HasFilters;
class PostTable extends Component
{
use HasFilters;
public function getQuery()
{
return Post::query();
}
}
filter() in API resources to standardize query params.Request to test filters:
$request = Request::create('/posts', 'GET', ['filters' => ['title' => ['$contains' => 'test']]]);
$this->app->instance('request', $request);
Field Name Mismatches:
filters[author.name] fails, ensure the relation is defined in the model and the field is allowed.dd(Request::all()) to verify incoming params.Database-Specific Quirks:
filters[order][$gt]=1).ILIKE (configure in config/purity.php).Silent Mode:
422 errors. Disable in config:
'silent' => true,
Nested Relations:
with():
Post::with('author')->filter()->get();
Performance:
limit()/offset().select() to limit columns:
Post::select('id', 'title')->filter()->get();
Log Filters:
Add to app/Providers/AppServiceProvider.php:
Purity::macro('debug', function () {
\Log::debug('Filters:', Request::query('filters'));
return $this;
});
Usage:
Post::filter()->debug()->get();
Query Inspection:
Use Laravel Debugbar or toSql():
$query = Post::filter()->toSql();
\Log::info($query);
Custom Resolver: Override the default filter resolver:
Purity::setResolver(function ($query, $filters) {
// Custom logic
return $query->where('custom_logic', $filters);
});
Dynamic Field Whitelisting:
Use a closure in config/purity.php:
'allowed_fields' => function () {
return auth()->user()->can('admin') ? ['*'] : ['title', 'published_at'];
},
Filter Groups: Combine filters with logical operators:
// URL: /posts?filters[0][title][$contains]=term&filters[1][status][$eq]=published
Post::filter()->get();
Use $and/$or for grouped logic:
// URL: /posts?filters[$and][0][title][$contains]=term&filters[$and][1][status][$eq]=published
Sorting Nulls:
Configure null handling in config/purity.php:
'sort_nulls' => 'last', // or 'first'
How can I help you explore Laravel packages today?