laravel-smart-filter maintained by sharifuddin
Description
Advanced smart filtering for Laravel Eloquent models with relation support and multiple filter types
Author
Last update
2025/11/02 09:57
(dev-main)
License
Downloads
3
Tags
filter - laravel - relations - eloquent - filtering - query-builder - laravel-filter - eloquent-filter - smart-filter - advanced-filter
🚀 Introduction
Laravel Smart Filter is a powerful and flexible filtering engine for Eloquent models.
It enables dynamic, request-driven filtering across columns and relationships — with support for multiple operators, data types, and nested relations.
✨ Features
- ⚡ Dynamic Filtering — Filter data using arrays or request parameters
- 🔍 Relation Filtering — Automatically filters related models
- 🧩 Multiple Operators —
=,!=,>,<,like,in,between,null, etc. - ⚙️ Type-Aware Parsing — Handles string, numeric, boolean, and date types
- 🔄 Request Integration — Parse filters directly from HTTP requests
- 🧪 Fully Tested & Configurable — Comprehensive test coverage and flexible config
📦 Installation
Requirements
- PHP 8.1 or higher
- Laravel 10.x, 11.x, or 12.x
Install via Composer
composer require sharifuddin/laravel-smart-filter
(Optional) Publish Configuration
php artisan vendor:publish --provider="Sharifuddin\\LaravelSmartFilter\\SmartFilterServiceProvider" --tag="smart-filter-config"
🎯 Quick Start
1️⃣ Add the Trait to a Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Sharifuddin\LaravelSmartFilter\Traits\SmartFilter;
class Product extends Model
{
use SmartFilter;
public function getFilterableFields(): array
{
return [
'name' => ['operator' => 'like', 'type' => 'string'],
'price' => ['operator' => 'between', 'type' => 'float'],
'category_id' => ['operator' => 'in', 'type' => 'integer'],
'is_active' => ['operator' => '=', 'type' => 'boolean'],
'created_at' => ['operator' => 'date', 'type' => 'date'],
];
}
public function getFilterableRelations(): array
{
return [
'category' => [
'fields' => ['name', 'slug'],
'max_depth' => 1,
],
'brand' => [
'fields' => ['name', 'description'],
'max_depth' => 1,
],
];
}
}
🧩 Usage Examples
🔹 Basic Filtering
$filters = [
'name' => ['value' => 'Laptop', 'operator' => 'like', 'type' => 'string'],
'price' => ['value' => [100, 1000], 'operator' => 'between', 'type' => 'float'],
'is_active' => ['value' => true, 'operator' => '=', 'type' => 'boolean'],
];
$products = Product::applySmartFilters($filters)->get();
🔹 Filter from HTTP Request
// Example URL: /products?name=Laptop&price_min=100&price_max=1000&category_id=1,2,3
$products = Product::filterFromRequest()->paginate(20);
specify allowed filters:
$products = Product::filterFromRequest([
'name' => ['operator' => 'like', 'type' => 'string'],
'price' => ['operator' => 'between', 'type' => 'float'],
'category_id' => ['operator' => 'in', 'type' => 'integer'],
])->get();
🔹 Relation Filtering
$filters = [
'category.name' => ['value' => 'Electronics', 'operator' => 'like', 'type' => 'string'],
'brand.name' => ['value' => 'Apple', 'operator' => 'like', 'type' => 'string'],
];
$products = Product::applySmartFilters($filters)->get();
🔹 Combined Example (Controller)
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function index(Request $request)
{
$products = Product::filterFromRequest([
'name' => ['operator' => 'like', 'type' => 'string'],
'price' => ['operator' => 'between', 'type' => 'float'],
'category_id' => ['operator' => 'in', 'type' => 'integer'],
'is_active' => ['operator' => '=', 'type' => 'boolean'],
])
->with(['category', 'brand'])
->orderBy('created_at', 'desc')
->paginate(24);
return view('products.index', compact('products'));
}
}
⚙️ Configuration
config/smart-filter.php
return [
'defaults' => [
'deep' => true,
'max_relation_depth' => 2,
'case_sensitive' => false,
'strict_mode' => false,
],
'fields' => [
'excluded' => ['id', 'created_at', 'updated_at', 'deleted_at', 'password'],
'default_operators' => [
'string' => 'like',
'integer' => '=',
'float' => '=',
'boolean' => '=',
'date' => '=',
'array' => 'in',
],
],
'request' => [
'prefix' => '',
'array_delimiter' => ',',
'date_format' => 'Y-m-d',
],
'performance' => [
'max_join_tables' => 5,
'query_timeout' => 30,
'max_filters' => 20,
],
];
🧪 Testing
# Run all tests
composer test
# With coverage
composer test-coverage
Example test:
public function test_filters_products_by_price_and_status()
{
$filters = [
'price' => ['value' => [100, 500], 'operator' => 'between', 'type' => 'float'],
'is_active' => ['value' => true, 'operator' => '=', 'type' => 'boolean'],
];
$products = Product::applySmartFilters($filters)->get();
$this->assertTrue($products->every(fn($p) => $p->is_active));
}
🧠 API Reference
➤ scopeApplySmartFilters()
public function scopeApplySmartFilters(
Builder $query,
array $filters = [],
array $options = []
): Builder
➤ scopeFilterFromRequest()
public function scopeFilterFromRequest(
Builder $query,
array $allowedFilters = [],
array $options = []
): Builder
🧰 Performance Tips
- Use indexed columns for frequent filters
- Prefer exact (
=) overLIKEfor faster queries - Limit filters using config:
max_filters - Always paginate large results
🤝 Contributing
Contributions are welcome!
See CONTRIBUTING.md for details.
📄 License
This package is open-sourced software licensed under the MIT License.