yared / laravel-smart-filter
Automatically convert HTTP query parameters into Eloquent query filters for Laravel APIs
Package info
github.com/yared-ayele-debela/laravel-smart-filter
pkg:composer/yared/laravel-smart-filter
Requires
- php: ^8.1
- illuminate/database: ^9.0|^10.0|^11.0|^12.0
- illuminate/http: ^9.0|^10.0|^11.0|^12.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0
This package is auto-updated.
Last update: 2026-05-08 22:05:07 UTC
README
A professional Laravel package that automatically converts HTTP query parameters into Eloquent query filters. Eliminate repetitive filtering logic in your Laravel APIs.
Instead of writing manual filtering logic in controllers, simply write:
Screenshot: Products page with quick filter links (All, Price > 100, Search, Category, Sort, etc.) and a table displaying filtered results.
Product::filter()->get();
The package automatically parses request query parameters and applies filters.
Installation
composer require yared/laravel-smart-filter
The package supports Laravel auto-discovery. For manual registration, add the service provider to config/app.php:
'providers' => [ // ... Yared\SmartFilter\SmartFilterServiceProvider::class, ],
Publish Configuration (Optional)
php artisan vendor:publish --tag=smart-filter-config
Quick Start
1. Add the Trait to Your Model
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Yared\SmartFilter\Traits\HasSmartFilter; class Product extends Model { use HasSmartFilter; }
2. Use in Your Controller
<?php namespace App\Http\Controllers; use App\Models\Product; class ProductController extends Controller { public function index() { return Product::filter()->paginate(); } }
That's it! Your API now supports automatic filtering from query parameters.
Before/After: Compare verbose manual filtering logic in controllers vs. the single-line Product::filter()->paginate() approach.
Supported Filter Types
Basic Equality
/api/products?category=phone
Comparison Operators
| Parameter | Example | SQL Equivalent |
|---|---|---|
| Greater than | ?price>100 |
WHERE price > 100 |
| Less than | ?price<500 |
WHERE price < 500 |
| Greater or equal | ?price>=100 |
WHERE price >= 100 |
| Less or equal | ?price<=500 |
WHERE price <= 500 |
| Not equal | ?status!=draft |
WHERE status != 'draft' |
Range Filters
/api/products?price_between=100,500
Applies WHERE price BETWEEN 100 AND 500.
Sorting
/api/products?sort=-price # Descending order
/api/products?sort=price # Ascending order
/api/products?sort=-price,name # Multiple columns
Search
/api/products?search=iphone
Applies LIKE %iphone% across configurable searchable columns (default: name, description).
Relationship Filtering
Filter by related model attributes using dot notation:
/api/products?category.name=electronics
Internally converts to:
$query->whereHas('category', function ($q) { $q->where('name', 'electronics'); });
Supports nested relationships: ?category.parent.name=electronics
Natural Language Filtering
Human-readable filter syntax:
/api/products?filter=price > 100 and stock > 0
Supported operators: >, <, >=, <=, =, !=
Logical operators: and, or
JSON Column Filtering
/api/products?attributes->color=red
Pagination
/api/products?page=2&per_page=10
Debug Mode
Add debug=true to see what filters were applied:
/api/products?price>100&category=phone&debug=true
Response includes metadata:
{
"data": [...],
"filters_applied": [
"price > 100",
"category = phone"
],
"sorting": "price DESC"
}
For debug metadata with pagination, use filterAndPaginate():
return Product::filterAndPaginate();
Debug mode: API response with filters_applied and sorting metadata when ?debug=true is used.
Configuration
Publish the config file and customize:
// config/smart-filter.php return [ 'searchable' => ['name', 'description'], 'reserved' => ['page', 'per_page', 'sort', 'search', 'filter', 'debug'], 'range_suffix' => '_between', ];
Model-Specific Searchable Columns
Override searchable columns per model:
Option 1: Property
class Product extends Model { use HasSmartFilter; protected array $searchable = ['name', 'description', 'sku']; }
Option 2: Method
class Product extends Model { use HasSmartFilter; public function getSearchableColumns(): array { return ['name', 'description', 'sku']; } }
Option 3: Inline Options
Product::filter(request(), ['searchable' => ['name', 'sku']])->get();
API Usage Examples
| Request | Description |
|---|---|
/api/products?price>100 |
Price greater than 100 |
/api/products?price>100&price<500 |
Price between 100 and 500 |
/api/products?category=phone |
Category equals phone |
/api/products?category.name=electronics |
Related category name |
/api/products?search=iphone |
Search in name/description |
/api/products?sort=-price |
Sort by price descending |
/api/products?filter=price > 100 and stock > 0 |
Natural language |
/api/products?price_between=100,500 |
Range filter |
/api/products?attributes->color=red |
JSON column |
/api/products?price>100&debug=true |
With debug metadata |
Architecture
The package follows clean architecture with separated responsibilities:
- QueryParser - Parses HTTP query parameters into structured filter data
- FilterBuilder - Applies parsed filters to Eloquent queries
- QueryDebugger - Records and outputs applied filters for debugging
Architecture: Request with query params flows through QueryParser, FilterBuilder, and into Eloquent.
Facade (Optional)
Register the facade in config/app.php:
'aliases' => [ 'SmartFilter' => Yared\SmartFilter\Facades\SmartFilter::class, ],
Usage:
use SmartFilter; $query = Product::query(); SmartFilter::apply($query); $products = $query->get();
Requirements
- PHP 8.1+
- Laravel 9.x, 10.x, 11.x, or 12.x
License
MIT License