{"id":20239984,"url":"https://github.com/thavarshan/filterable","last_synced_at":"2025-05-16T05:05:09.378Z","repository":{"id":232059304,"uuid":"783359358","full_name":"Thavarshan/filterable","owner":"Thavarshan","description":"🔍 Enhance Laravel queries with adaptable, customisable filters and intelligent caching to improve both performance and functionality.","archived":false,"fork":false,"pushed_at":"2025-05-12T10:47:18.000Z","size":284,"stargazers_count":165,"open_issues_count":0,"forks_count":9,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-12T11:44:16.965Z","etag":null,"topics":["database-queries","eloquent","eloquent-orm","eloquent-orm-models","filter","filterable","laravel"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Thavarshan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":".github/SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"thavarshan","buy_me_a_coffee":"thavarshan"}},"created_at":"2024-04-07T17:13:46.000Z","updated_at":"2025-05-12T10:47:16.000Z","dependencies_parsed_at":"2024-04-10T16:29:33.246Z","dependency_job_id":"8e70f4d4-ac0c-4ad8-9183-b6fdf68d4f3c","html_url":"https://github.com/Thavarshan/filterable","commit_stats":null,"previous_names":["thavarshan/filterable"],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thavarshan%2Ffilterable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thavarshan%2Ffilterable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thavarshan%2Ffilterable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thavarshan%2Ffilterable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Thavarshan","download_url":"https://codeload.github.com/Thavarshan/filterable/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471061,"owners_count":22076585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database-queries","eloquent","eloquent-orm","eloquent-orm-models","filter","filterable","laravel"],"created_at":"2024-11-14T08:42:31.874Z","updated_at":"2025-05-16T05:05:09.371Z","avatar_url":"https://github.com/Thavarshan.png","language":"PHP","readme":"[![Filterable](./assets/Banner.jpg)](https://github.com/Thavarshan/filterable)\n\n# About Filterable\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/jerome/filterable.svg)](https://packagist.org/packages/jerome/filterable)\n[![Tests](https://github.com/Thavarshan/filterable/actions/workflows/tests.yml/badge.svg?label=tests\u0026branch=main)](https://github.com/Thavarshan/filterable/actions/workflows/tests.yml)\n[![Lint](https://github.com/Thavarshan/filterable/actions/workflows/lint.yml/badge.svg)](https://github.com/Thavarshan/filterable/actions/workflows/lint.yml)\n[![CodeQL](https://github.com/Thavarshan/filterable/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/Thavarshan/filterable/actions/workflows/github-code-scanning/codeql)\n[![PHPStan](https://img.shields.io/badge/PHPStan-level%20max-brightgreen.svg)](https://phpstan.org/)\n[![PHP Version](https://img.shields.io/packagist/php-v/jerome/filterable.svg)](https://packagist.org/packages/jerome/filterable)\n[![License](https://img.shields.io/packagist/l/jerome/filterable.svg)](https://packagist.org/packages/jerome/filterable)\n[![Total Downloads](https://img.shields.io/packagist/dt/jerome/filterable.svg)](https://packagist.org/packages/jerome/filterable)\n[![GitHub Stars](https://img.shields.io/github/stars/Thavarshan/filterable.svg?style=social\u0026label=Stars)](https://github.com/Thavarshan/filterable/stargazers)\n\nThe `Filterable` package provides a robust, feature-rich solution for applying dynamic filters to Laravel's Eloquent queries. With a modular, trait-based architecture, it supports advanced features like intelligent caching, user-specific filtering, performance monitoring, memory management, and much more. It's suitable for applications of any scale, from simple blogs to complex enterprise-level data platforms.\n\n## Requirements\n\n- PHP 8.2+\n- Laravel 10.x, 11.x, or 12.x\n\n## Features\n\n- **Dynamic Filtering**: Apply filters based on request parameters with ease\n- **Modular Architecture**: Customize your filter implementation using traits\n- **Smart Caching**: Both simple and intelligent caching strategies with automatic cache key generation\n- **User-Specific Filtering**: Easily implement user-scoped filters\n- **Rate Limiting**: Control filter complexity and prevent abuse\n- **Validation**: Validate filter inputs before processing\n- **Permission Control**: Apply permission-based access to specific filters\n- **Performance Monitoring**: Track execution time and query performance\n- **Memory Management**: Optimize memory usage for large datasets with lazy loading and chunking\n- **Query Optimization**: Intelligent query building with column selection and relationship loading\n- **Logging**: Comprehensive logging capabilities for debugging and monitoring\n- **Filter Chaining**: Chain multiple filter operations with a fluent API\n- **Value Transformation**: Transform input values before applying filters\n- **Custom Pre-Filters**: Register filters to run before the main filters\n- **Comprehensive Debugging**: Detailed debug information about applied filters and query execution\n- **Conditional Execution**: Use Laravel's conditionable trait for conditional filter application\n- **Smart Error Handling**: Graceful handling of filtering exceptions\n- **Flexible State Management**: Monitor and manage the filter execution state\n- **Chainable Configuration**: Fluent API for configuration with method chaining\n\n## Installation\n\nTo integrate the `Filterable` package into your Laravel project, install it via Composer:\n\n```bash\ncomposer require jerome/filterable\n```\n\nThe package automatically registers its service provider with Laravel's service container through auto-discovery (Laravel 5.5+).\n\nFor older Laravel versions, manually register the `FilterableServiceProvider` in your `config/app.php` file:\n\n```php\n'providers' =\u003e [\n    // Other service providers...\n    Filterable\\Providers\\FilterableServiceProvider::class,\n],\n```\n\n## Usage\n\n### Creating a Filter Class\n\nCreate a new filter class using the Artisan command:\n\n```bash\nphp artisan make:filter PostFilter\n```\n\nThis command supports several options:\n\n| Option | Shortcut | Description |\n|--------|----------|-------------|\n| `--basic` | `-b` | Creates a basic filter class with minimal functionality |\n| `--model=ModelName` | `-m ModelName` | Generates a filter for the specified model |\n| `--force` | `-f` | Creates the class even if the filter already exists |\n\nExamples:\n\n```bash\n# Create a basic filter\nphp artisan make:filter PostFilter --basic\n\n# Create a filter for a specific model\nphp artisan make:filter PostFilter --model=Post\n\n# Force creation of a filter\nphp artisan make:filter PostFilter --force\n\n# Combine options\nphp artisan make:filter PostFilter --model=Post --force\n```\n\nThe command generates a filter class in the `app/Filters` directory. Extend the base `Filter` class to implement your specific filtering logic:\n\n```php\nnamespace App\\Filters;\n\nuse Filterable\\Filter;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Contracts\\Cache\\Repository as Cache;\nuse Psr\\Log\\LoggerInterface;\n\nclass PostFilter extends Filter\n{\n    protected array $filters = ['status', 'category'];\n\n    /**\n     * Enable specific features for this filter.\n     */\n    public function __construct(Request $request, ?Cache $cache = null, ?LoggerInterface $logger = null)\n    {\n        parent::__construct($request, $cache, $logger);\n\n        // Enable the features you need\n        $this-\u003eenableFeatures([\n            'validation',\n            'caching',\n            'logging',\n            'performance',\n        ]);\n    }\n\n    protected function status(string $value): Builder\n    {\n        return $this-\u003ebuilder-\u003ewhere('status', $value);\n    }\n\n    protected function category(int $value): Builder\n    {\n        return $this-\u003ebuilder-\u003ewhere('category_id', $value);\n    }\n}\n```\n\n#### Adding Custom Filters\n\nTo add a new filter, define a method within your filter class using **camelCase** naming, and register it in the `$filters` array:\n\n```php\nprotected array $filters = ['last_published_at'];\n\nprotected function lastPublishedAt(string $value): Builder\n{\n    return $this-\u003ebuilder-\u003ewhere('last_published_at', $value);\n}\n```\n\n### Implementing the `Filterable` Trait and Interface\n\nApply the `Filterable` interface and trait to your Eloquent models:\n\n```php\nnamespace App\\Models;\n\nuse Filterable\\Interfaces\\Filterable as FilterableInterface;\nuse Filterable\\Traits\\Filterable as FilterableTrait;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Post extends Model implements FilterableInterface\n{\n    use FilterableTrait;\n}\n```\n\n### Applying Filters\n\nBasic usage:\n\n```php\nuse App\\Models\\Post;\nuse App\\Filters\\PostFilter;\n\n$filter = new PostFilter(request(), cache(), logger());\n$posts = Post::filter($filter)-\u003eget();\n```\n\nIn a controller:\n\n```php\nuse App\\Models\\Post;\nuse App\\Filters\\PostFilter;\nuse Illuminate\\Http\\Request;\n\nclass PostController extends Controller\n{\n    public function index(Request $request, PostFilter $filter)\n    {\n        $query = Post::filter($filter);\n\n        $posts = $request-\u003ehas('paginate')\n            ? $query-\u003epaginate($request-\u003equery('per_page', 20))\n            : $query-\u003eget();\n\n        return response()-\u003ejson($posts);\n    }\n}\n```\n\n### Laravel 12 Support\n\nFor Laravel 12, which has moved to a more minimal initial setup, make sure to follow these additional steps:\n\n1. **Service Registration**: If you're using a minimal Laravel 12 application, you may need to manually register the service provider in your `bootstrap/providers.php` file:\n\n```php\nreturn [\n    // Other service providers...\n    Filterable\\Providers\\FilterableServiceProvider::class,\n];\n```\n\n2. **Invokable Controllers**: If you're using Laravel 12's invokable controllers, here's how to apply filters:\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Post;\nuse App\\Filters\\PostFilter;\nuse Illuminate\\Http\\Request;\n\nclass PostIndexController extends Controller\n{\n    public function __invoke(Request $request, PostFilter $filter)\n    {\n        $query = Post::filter($filter);\n\n        $posts = $request-\u003ehas('paginate')\n            ? $query-\u003epaginate($request-\u003equery('per_page', 20))\n            : $query-\u003eget();\n\n        return response()-\u003ejson($posts);\n    }\n}\n```\n\n3. **Route Registration**: Using the new routing style in Laravel 12:\n\n```php\nuse App\\Http\\Controllers\\PostIndexController;\n\nRoute::get('/posts', PostIndexController::class);\n```\n\n### Advanced Features\n\n#### Feature Management\n\nSelectively enable features for your filter:\n\n```php\n// Enable individual features\n$filter-\u003eenableFeature('validation');\n$filter-\u003eenableFeature('caching');\n\n// Enable multiple features at once\n$filter-\u003eenableFeatures([\n    'validation',\n    'caching',\n    'logging',\n    'performance',\n]);\n\n// Disable a feature\n$filter-\u003edisableFeature('caching');\n\n// Check if a feature is enabled\nif ($filter-\u003ehasFeature('caching')) {\n    // Do something\n}\n```\n\n##### Available Features\n\nThe Filterable package supports the following features that can be enabled or disabled:\n\n| Feature | Description |\n|---------|-------------|\n| `validation` | Validates filter inputs before applying them |\n| `permissions` | Enables permission-based access to filters |\n| `rateLimit` | Controls filter complexity and prevents abuse |\n| `caching` | Caches query results for improved performance |\n| `logging` | Provides comprehensive logging capabilities |\n| `performance` | Monitors execution time and query performance |\n| `optimization` | Optimizes queries with selective columns and eager loading |\n| `memoryManagement` | Optimizes memory usage for large datasets |\n| `filterChaining` | Enables fluent chaining of multiple filter operations |\n| `valueTransformation` | Transforms input values before applying filters |\n\nEach feature can be enabled independently based on your specific needs:\n\n```php\n// Enable all features\n$filter-\u003eenableFeatures([\n    'validation',\n    'permissions',\n    'rateLimit',\n    'caching',\n    'logging',\n    'performance',\n    'optimization',\n    'memoryManagement',\n    'filterChaining',\n    'valueTransformation',\n]);\n```\n\n#### User-Scoped Filtering\n\nApply filters that are specific to the authenticated user:\n\n```php\n$filter-\u003eforUser($request-\u003euser());\n```\n\n#### Pre-Filters\n\nApply pre-filters that run before the main filters:\n\n```php\n$filter-\u003eregisterPreFilters(function (Builder $query) {\n    return $query-\u003ewhere('published', true);\n});\n```\n\n#### Validation\n\nSet validation rules for your filter inputs:\n\n```php\n$filter-\u003esetValidationRules([\n    'status' =\u003e 'required|in:active,inactive',\n    'category_id' =\u003e 'sometimes|integer|exists:categories,id',\n]);\n\n// Add custom validation messages\n$filter-\u003esetValidationMessages([\n    'status.in' =\u003e 'Status must be either active or inactive',\n]);\n```\n\n#### Permission Control\n\nDefine permission requirements for specific filters:\n\n```php\n$filter-\u003esetFilterPermissions([\n    'admin_only_filter' =\u003e 'admin',\n    'editor_filter' =\u003e ['editor', 'admin'],\n]);\n\n// Implement the permission check in your filter class\nprotected function userHasPermission(string|array $permission): bool\n{\n    if (is_array($permission)) {\n        return collect($permission)-\u003econtains(fn ($role) =\u003e $this-\u003eforUser-\u003ehasRole($role));\n    }\n\n    return $this-\u003eforUser-\u003ehasRole($permission);\n}\n```\n\n#### Rate Limiting\n\nControl the complexity of filter requests:\n\n```php\n// Set the maximum number of filters that can be applied at once\n$filter-\u003esetMaxFilters(10);\n\n// Set the maximum complexity score for all filters combined\n$filter-\u003esetMaxComplexity(100);\n\n// Define complexity scores for specific filters\n$filter-\u003esetFilterComplexity([\n    'complex_filter' =\u003e 10,\n    'simple_filter' =\u003e 1,\n]);\n```\n\n#### Memory Management\n\nOptimize memory usage for large datasets:\n\n```php\n// Process a query with lazy loading\n$posts = $filter-\u003elazy()-\u003eeach(function ($post) {\n    // Process each post with minimal memory usage\n});\n\n// Use chunking for large datasets\n$filter-\u003echunk(1000, function ($posts) {\n    // Process posts in chunks of 1000\n});\n\n// Map over query results without loading all records\n$result = $filter-\u003emap(function ($post) {\n    return $post-\u003etitle;\n});\n\n// Filter results without loading all records\n$result = $filter-\u003efilter(function ($post) {\n    return $post-\u003estatus === 'active';\n});\n\n// Reduce results without loading all records\n$total = $filter-\u003ereduce(function ($carry, $post) {\n    return $carry + $post-\u003eviews;\n}, 0);\n\n// Get a lazy collection with custom chunk size\n$lazyCollection = $filter-\u003elazy(500);\n\n// Process each item with minimal memory usage\n$filter-\u003elazyEach(function ($item) {\n    // Process item\n}, 500);\n\n// Create a generator to iterate with minimal memory\nforeach ($filter-\u003ecursor() as $item) {\n    // Process item\n}\n```\n\n#### Query Optimization\n\nOptimize database queries:\n\n```php\n// Select only needed columns\n$filter-\u003eselect(['id', 'title', 'status']);\n\n// Eager load relationships\n$filter-\u003ewith(['author', 'comments']);\n\n// Set chunk size for large datasets\n$filter-\u003echunkSize(1000);\n\n// Use a database index hint\n$filter-\u003euseIndex('idx_posts_status');\n```\n\n#### Caching\n\nConfigure caching behavior:\n\n```php\n// Set cache expiration time (in minutes)\n$filter-\u003esetCacheExpiration(60);\n\n// Manually clear the cache\n$filter-\u003eclearCache();\n\n// Use tagged cache for better invalidation\n$filter-\u003ecacheTags(['posts', 'api']);\n\n// Enable specific caching modes\n$filter-\u003ecacheResults(true);\n$filter-\u003ecacheCount(true);\n\n// Get the number of items with caching\n$count = $filter-\u003ecount();\n\n// Clear related caches when models change\n$filter-\u003eclearRelatedCaches(Post::class);\n\n// Get SQL query without executing it\n$sql = $filter-\u003etoSql();\n```\n\n#### Logging\n\nConfigure and use logging:\n\n```php\n// Set a custom logger\n$filter-\u003esetLogger($customLogger);\n\n// Get the current logger\n$logger = $filter-\u003egetLogger();\n\n// Log at different levels\n$filter-\u003elogInfo(\"Applying filter\", ['filter' =\u003e 'status']);\n$filter-\u003elogDebug(\"Filter details\", ['value' =\u003e $value]);\n$filter-\u003elogWarning(\"Potential issue\", ['problem' =\u003e 'description']);\n\n// Logging is automatically handled if enabled\n// You can also add custom logging in your filter methods:\nprotected function customFilter($value): Builder\n{\n    $this-\u003elogInfo(\"Applying custom filter with value: {$value}\");\n\n    return $this-\u003ebuilder-\u003ewhere('custom_field', $value);\n}\n```\n\n#### Performance Monitoring\n\nTrack and analyze filter performance:\n\n```php\n// Get performance metrics after applying filters\n$metrics = $filter-\u003egetMetrics();\n\n// Add custom metrics\n$filter-\u003eaddMetric('custom_metric', $value);\n\n// Get execution time\n$executionTime = $filter-\u003egetExecutionTime();\n```\n\n#### Filter Chaining\n\nChain multiple filter operations with a fluent API:\n\n```php\n$filter-\u003ewhere('status', 'active')\n       -\u003ewhereIn('category_id', [1, 2, 3])\n       -\u003ewhereNotIn('tag_id', [4, 5])\n       -\u003ewhereBetween('created_at', [$startDate, $endDate])\n       -\u003eorderBy('created_at', 'desc');\n```\n\n#### Value Transformation\n\nTransform filter values before applying them:\n\n```php\n// Register a transformer for a filter\n$filter-\u003eregisterTransformer('date', function ($value) {\n    return Carbon::parse($value)-\u003etoDateTimeString();\n});\n\n// Register a transformer for an array of values\n$arrayTransformer = function($values) {\n    return array_map(fn($value) =\u003e strtolower($value), $values);\n};\n$filter-\u003eregisterTransformer('tags', $arrayTransformer);\n```\n\n#### Conditional Execution\n\nUse Laravel's conditionable trait for conditional filter application:\n\n```php\n// Only apply a filter if a condition is met\n$filter-\u003ewhen($request-\u003ehas('status'), function ($filter) use ($request) {\n    $filter-\u003ewhere('status', $request-\u003estatus);\n});\n\n// Apply one filter or another based on a condition\n$filter-\u003ewhen($request-\u003ehas('sort'),\n    function ($filter) use ($request) {\n        $filter-\u003eorderBy($request-\u003esort);\n    },\n    function ($filter) {\n        $filter-\u003eorderBy('created_at', 'desc');\n    }\n);\n```\n\n#### State Management\n\nMonitor and manage the filter execution state:\n\n```php\n// Check the current state\nif ($filter-\u003egetDebugInfo()['state'] === 'applied') {\n    // Process results\n}\n\n// Reset the filter to its initial state\n$filter-\u003ereset();\n```\n\n#### Debug Information\n\nGet detailed information about the applied filters:\n\n```php\n$debugInfo = $filter-\u003egetDebugInfo();\n\n// Debug info includes:\n// - Current state\n// - Applied filters\n// - Enabled features\n// - Query options\n// - SQL query and bindings\n// - Performance metrics (if enabled)\n```\n\n#### Error Handling\n\nCustomize exception handling for your filters:\n\n```php\nclass MyFilter extends Filter\n{\n    protected function handleFilteringException(Throwable $exception): void\n    {\n        // Log the exception\n        $this-\u003elogWarning('Filter exception', [\n            'message' =\u003e $exception-\u003egetMessage(),\n            'trace' =\u003e $exception-\u003egetTraceAsString(),\n        ]);\n\n        // Optionally rethrow specific exceptions\n        if ($exception instanceof MyCustomException) {\n            throw $exception;\n        }\n\n        // Otherwise, let the parent handle it\n        parent::handleFilteringException($exception);\n    }\n}\n```\n\n### Complete Example\n\n```php\nuse App\\Models\\Post;\nuse App\\Filters\\PostFilter;\nuse Illuminate\\Http\\Request;\n\nclass PostController extends Controller\n{\n    public function index(Request $request, PostFilter $filter)\n    {\n        // Enable features\n        $filter-\u003eenableFeatures([\n            'validation',\n            'caching',\n            'logging',\n            'performance',\n        ]);\n\n        // Set validation rules\n        $filter-\u003esetValidationRules([\n            'status' =\u003e 'sometimes|in:active,inactive',\n            'category_id' =\u003e 'sometimes|integer|exists:categories,id',\n        ]);\n\n        // Apply user scope\n        $filter-\u003eforUser($request-\u003euser());\n\n        // Apply pre-filters\n        $filter-\u003eregisterPreFilters(function ($query) {\n            return $query-\u003ewhere('published', true);\n        });\n\n        // Set caching options\n        $filter-\u003esetCacheExpiration(30);\n        $filter-\u003ecacheTags(['posts', 'api']);\n\n        // Apply custom filter chain\n        $filter-\u003ewhere('is_featured', true)\n               -\u003eorderBy('created_at', 'desc');\n\n        // Apply filters to the query\n        $query = Post::filter($filter);\n\n        // Get paginated results\n        $posts = $request-\u003ehas('paginate')\n            ? $query-\u003epaginate($request-\u003equery('per_page', 20))\n            : $query-\u003eget();\n\n        // Get performance metrics if needed\n        $metrics = null;\n        if ($filter-\u003ehasFeature('performance')) {\n            $metrics = $filter-\u003egetMetrics();\n        }\n\n        return response()-\u003ejson([\n            'data' =\u003e $posts,\n            'metrics' =\u003e $metrics,\n        ]);\n    }\n}\n```\n\n## Frontend Usage\n\nSend filter parameters as query parameters:\n\n```typescript\n// Filter posts by status\nconst response = await fetch('/posts?status=active');\n\n// Combine multiple filters\nconst response = await fetch('/posts?status=active\u0026category_id=2\u0026is_featured=1');\n```\n\n## Testing\n\nTesting your filters using PHPUnit:\n\n```php\nnamespace Tests\\Unit;\n\nuse Tests\\TestCase;\nuse App\\Models\\Post;\nuse App\\Filters\\PostFilter;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Illuminate\\Http\\Request;\n\nclass PostFilterTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function testFiltersPostsByStatus(): void\n    {\n        $activePost = Post::factory()-\u003ecreate(['status' =\u003e 'active']);\n        $inactivePost = Post::factory()-\u003ecreate(['status' =\u003e 'inactive']);\n\n        $filter = new PostFilter(new Request(['status' =\u003e 'active']));\n        $filteredPosts = Post::filter($filter)-\u003eget();\n\n        $this-\u003eassertTrue($filteredPosts-\u003econtains($activePost));\n        $this-\u003eassertFalse($filteredPosts-\u003econtains($inactivePost));\n    }\n\n    public function testRateLimitingRejectsComplexQueries(): void\n    {\n        // Create a filter with too many parameters\n        $filter = new PostFilter(new Request([\n            'param1' =\u003e 'value1',\n            'param2' =\u003e 'value2',\n            // ... many more parameters\n        ]));\n\n        $filter-\u003eenableFeature('rateLimit');\n        $filter-\u003esetMaxFilters(5);\n\n        // Apply the filter and check if rate limiting was triggered\n        $result = Post::filter($filter)-\u003eget();\n\n        // Assert that no results were returned due to rate limiting\n        $this-\u003eassertEmpty($result);\n    }\n}\n```\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.\n\n## Contributing\n\nContributions are welcome and greatly appreciated! If you have suggestions to make this package better, please fork the repository and create a pull request, or open an issue with the tag \"enhancement\".\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/amazing-feature`)\n3. Commit your Changes (`git commit -m 'Add some amazing-feature'`)\n4. Push to the Branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## Authors\n\n- **[Jerome Thayananthajothy]** - *Initial work* - [Thavarshan](https://github.com/Thavarshan)\n\nSee also the list of [contributors](https://github.com/Thavarshan/filterable/contributors) who participated in this project.\n\n## Acknowledgments\n\n- Hat tip to Spatie for their [query builder](https://github.com/spatie/laravel-query-builder) package, which inspired this project.\n","funding_links":["https://github.com/sponsors/thavarshan","https://buymeacoffee.com/thavarshan"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthavarshan%2Ffilterable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthavarshan%2Ffilterable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthavarshan%2Ffilterable/lists"}