### Basic PostFilter Class Example Source: https://github.com/thavarshan/filterable/wiki/Filterable Example of a basic PostFilter class extending the base Filter class, demonstrating how to define filter methods for status and category. ```php namespace App\Filters; use Filterable\Filter; use Illuminate\Database\Eloquent\Builder; class PostFilter extends Filter { protected array $filters = ['status', 'category']; protected function status(string $value): Builder { return $this->builder->where('status', $value); } protected function category(int $value): Builder { return $this->builder->where('category_id', $value); } } ``` -------------------------------- ### Development Workflow Commands in Bash Source: https://github.com/thavarshan/filterable/blob/main/CLAUDE.md This snippet outlines bash commands for installing dependencies, running linting, formatting code, executing tests, and performing static analysis in the Filterable project. It depends on Composer, PHPUnit, and tools like Pint, Duster, and PHPStan. Inputs are command-line flags for focused testing, coverage, or strict mode; outputs include logs, test results, or non-zero exit on failures. Limitations include requiring MySQL env vars or driver stubbing for tests. ```bash composer install # install dependencies composer lint # run Duster + syntax checks via bin/lint.sh composer fix # apply Pint/Duster formatting (logs to file) composer test # run PHPUnit through bin/test.sh ./bin/test.sh --filter=HandlesRateLimitingTest # focused tests ./bin/test.sh --coverage # coverage (requires Xdebug) ./bin/test.sh --parallel # parallel runs ./bin/lint.sh --strict # non-zero exit on lint issues vendor/bin/phpstan analyse # static analysis (level max) ``` -------------------------------- ### Install Filterable Package via Composer Source: https://github.com/thavarshan/filterable/wiki/Filterable Command to install the Filterable package in a Laravel project using Composer. This package enhances Eloquent query capabilities with dynamic filtering. ```bash composer require jerome/filterable ``` -------------------------------- ### Frontend Filtering Request Example Source: https://github.com/thavarshan/filterable/wiki/Filterable Shows how to make HTTP requests from a frontend application to filter data. Query parameters are used to specify filter criteria, such as 'status' or 'category_id'. The backend interprets these parameters to narrow down the results. ```typescript const response = await fetch('/posts?status=active'); const data = await response.json(); ``` ```typescript const response = await fetch('/posts?status=active&category_id=2'); const data = await response.json(); ``` -------------------------------- ### API Frontend Integration Source: https://context7.com/thavarshan/filterable/llms.txt This section details how to integrate with the Filterable API from client-side applications using query string parameters. It includes examples for fetching posts and products with various filtering options. ```APIDOC ## GET /api/posts ### Description Fetches a list of posts with filtering capabilities. Supports various query parameters for status, category, publication date, and search terms. ### Method GET ### Endpoint `/api/posts` ### Parameters #### Query Parameters - **status** (string) - Optional - Filters posts by their status (e.g., 'published'). - **category_id** (integer) - Optional - Filters posts by their category ID. - **published_after** (string) - Optional - Filters posts published after a specific date (YYYY-MM-DD). - **q** (string) - Optional - Performs a full-text search on posts. - **per_page** (integer) - Optional - Specifies the number of posts per page for pagination. ### Request Example ```javascript const params = new URLSearchParams({ status: 'published', category_id: 5, published_after: '2025-01-01', q: 'laravel', per_page: 20 }); fetch(`/api/posts?${params.toString()}`); ``` ### Response #### Success Response (200) - **data** (array) - An array of post objects. - **links** (object) - Pagination links. - **meta** (object) - Pagination metadata. #### Response Example ```json { "data": [ { "id": 1, "title": "Example Post", "content": "This is the content." } ], "links": { "first": "...", "last": "..." }, "meta": { "current_page": 1, "per_page": 20, "total": 100 } } ``` ## GET /api/products ### Description Fetches a list of products with advanced filtering options, including tags and price ranges. ### Method GET ### Endpoint `/api/products` ### Parameters #### Query Parameters - **tags[]** (string) - Optional - Filters products by one or more tags. Can be specified multiple times for multiple tags. - **price_range[min]** (integer) - Optional - Filters products within a minimum price. - **price_range[max]** (integer) - Optional - Filters products within a maximum price. - **in_stock** (boolean) - Optional - Filters products that are currently in stock. ### Request Example ```javascript const params = new URLSearchParams(); params.append('tags[]', 'electronics'); params.append('tags[]', 'sale'); params.append('price_range[min]', '50'); params.append('price_range[max]', '500'); params.append('in_stock', 'true'); fetch(`/api/products?${params.toString()}`); ``` ### Response #### Success Response (200) - **data** (array) - An array of product objects. - **links** (object) - Pagination links. - **meta** (object) - Pagination metadata. #### Response Example ```json { "data": [ { "id": 101, "name": "Example Product", "price": 199.99, "tags": ["electronics", "sale"] } ], "links": { "first": "...", "last": "..." }, "meta": { "current_page": 1, "per_page": 20, "total": 50 } } ``` ``` -------------------------------- ### Setup Custom Logging Channel Directly in PHP Source: https://github.com/thavarshan/filterable/wiki/Filterable Create a Monolog logger with a custom channel for the Filter class. Uses StreamHandler for file logging. Inputs: channel name and log path; outputs: dedicated logger instance. Provides full control without framework config. ```php use Monolog\Logger; use Monolog\Handler\StreamHandler; // Create a logger instance for the Filter class with a custom channel $logger = new Logger('filter'); $logger->pushHandler(new StreamHandler(storage_path('logs/filter.log'), Logger::DEBUG)); // Set the logger to the filter class $filter->setLogger($logger); ``` -------------------------------- ### Implement Filterable in Post Model Source: https://github.com/thavarshan/filterable/wiki/Filterable Example of implementing the Filterable interface and using the Filterable trait in a Laravel Eloquent Post model to enable filtering. ```php namespace App\Models; use Filterable\Interfaces\Filterable as FilterableInterface; use Filterable\Traits\Filterable as FilterableTrait; use Illuminate\Database\Eloquent\Model; class Post extends Model implements FilterableInterface { use FilterableTrait; } ``` -------------------------------- ### Implement filtering logic in PHP Source: https://github.com/thavarshan/filterable/blob/main/README.md Defines a filter class with methods to handle different filter criteria. Includes setup for validation, optimization, and value transformation. Methods correspond to request keys for dynamic filtering. ```php enableFeatures([ 'validation', 'optimization', 'filterChaining', 'valueTransformation', ]); $this->setValidationRules([ 'status' => ['nullable', Rule::in(['draft', 'published'])], 'published_after' => ['nullable', 'date'], ]); $this->registerTransformer('published_after', fn ($value) => Carbon::parse($value)); $this->registerPreFilters(fn (Builder $query) => $query->where('is_visible', true)); $this->select(['id', 'title', 'status', 'published_at'])->with('author'); } protected function status(string $value): void { $this->getBuilder()->where('status', $value); } protected function publishedAfter(Carbon $date): void { $this->getBuilder()->whereDate('published_at', '>=', $date); } protected function q(string $term): void { $this->getBuilder()->where(function (Builder $query) use ($term) { $query->where('title', 'like', "%{$term}%") ->orWhere('body', 'like', "%{$term}%"); }); } } ``` -------------------------------- ### Creating a Custom PostFilter in PHP Source: https://github.com/thavarshan/filterable/blob/main/CLAUDE.md This PHP example demonstrates extending the abstract Filter class to create a PostFilter for handling status and date-based query filters on Eloquent models. It requires Laravel's Request and Builder classes, with features like validation and caching enabled via enableFeatures(). Inputs are HTTP request parameters mapped to methods like status(); outputs are modified query builders. Limitations include needing to define filter methods for each supported key and overriding defaults for custom mapping. ```php class PostFilter extends Filter { protected array $filters = ['status', 'published_at']; public function __construct(Request $request) { parent::__construct($request); $this->enableFeatures(['validation', 'caching', 'performance']); $this->setValidationRules([ 'status' => 'in:draft,published,archived', 'published_at' => 'date', ]); } protected function status(string $value): Builder { return $this->getBuilder()->where('status', $value); } } ``` -------------------------------- ### Adding a New Filter Method Source: https://github.com/thavarshan/filterable/wiki/Filterable Example showing how to add a new filter method 'lastPublishedAt' to the PostFilter class and register it in the $filters array. ```php namespace App\Filters; use Filterable\Filter; class PostFilter extends Filter { protected array $filters = ['last_published_at']; protected function lastPublishedAt(int $value): Builder { return $this->builder->where('last_published_at', $value); } } ``` -------------------------------- ### Configure Basic Logger with Monolog in PHP Source: https://github.com/thavarshan/filterable/wiki/Filterable Initialize a Monolog logger and set it on the Filter class for basic logging. Depends on Monolog library and PSR-3 interface. Inputs: logger name and file path; outputs: filter instance with logging enabled. Limitations: manual setup required outside Laravel. ```php use Monolog\Logger; use Monolog\Handler\StreamHandler; // Create a logger instance $logger = new Logger('name'); $logger->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING)); // Set the logger to the filter class $filter->setLogger($logger); ``` -------------------------------- ### Inject Logger via Laravel Dependency Injection Source: https://github.com/thavarshan/filterable/wiki/Filterable Use Laravel's service container to inject a logger into the Filter class. Relies on Laravel's app binding. Inputs: service provider setup; outputs: automatically injected logger. Suitable for framework-integrated applications. ```php // In a service provider or similar setup $this->app->when(Filter::class) ->needs(LoggerInterface::class) ->give(function () { return new Logger('name', [new StreamHandler('path/to/your.log', Logger::WARNING)]); }); ``` -------------------------------- ### Run filter pipeline in Laravel controller Source: https://github.com/thavarshan/filterable/blob/main/README.md Demonstrates how to apply a filter to a model query within a controller. Includes enabling features like caching and setting options for the filter. ```php filter( $filter ->forUser($request->user()) ->enableFeature('caching') ->setOptions(['chunk_size' => 500]) ) ->get(); return PostResource::collection($posts); } } ``` -------------------------------- ### Implement basic filter with validation and transformation Source: https://context7.com/thavarshan/filterable/llms.txt Demonstrates a filter implementation with validation rules, query optimization, value transformation, and filter chaining. Includes status filtering, date filtering, category filtering, and full-text search capabilities. ```php enableFeatures([ 'validation', 'optimization', 'filterChaining', 'valueTransformation', ]); $this->setValidationRules([ 'status' => ['nullable', Rule::in(['draft', 'published', 'archived'])], 'published_after' => ['nullable', 'date'], 'category_id' => ['nullable', 'integer', 'exists:categories,id'], 'q' => ['nullable', 'string', 'min:2'], ]); $this->registerTransformer('published_after', fn ($value) => Carbon::parse($value)); $this->registerPreFilters(fn (Builder $query) => $query->where('is_visible', true)); $this->select(['id', 'title', 'status', 'published_at'])->with('author', 'category'); } protected function status(string $value): void { $this->getBuilder()->where('status', $value); } protected function publishedAfter(Carbon $date): void { $this->getBuilder()->whereDate('published_at', '>=', $date); } protected function categoryId(int $id): void { $this->getBuilder()->where('category_id', $id); } protected function q(string $term): void { $this->getBuilder()->where(function (Builder $query) use ($term) { $query->where('title', 'like', "%{$term}%") ->orWhere('body', 'like', "%{$term}%"); }); } } ``` -------------------------------- ### Apply Filters to Eloquent Query Source: https://github.com/thavarshan/filterable/wiki/Filterable PHP code demonstrating how to apply a PostFilter to an Eloquent query for the Post model, using request and cache parameters. ```php use App\Models\Post; $filter = new PostFilter(request(), cache()); $posts = Post::filter($filter)->get(); ``` -------------------------------- ### Default Package Configuration (PHP) Source: https://context7.com/thavarshan/filterable/llms.txt This PHP file defines the default configuration for the filterable package. It specifies default feature flags such as validation, caching, and performance, along with default options for chunk size and cache TTL (Time To Live). These defaults can be overridden by individual filter configurations. ```php [ 'features' => [ 'validation' => false, 'permissions' => false, 'rateLimit' => false, 'caching' => false, 'logging' => false, 'performance' => true, // Enable globally 'optimization' => true, // Enable globally 'memoryManagement' => false, 'filterChaining' => false, 'valueTransformation' => false, ], 'options' => [ 'chunk_size' => 1000, 'use_chunking' => true, ], 'cache' => [ 'ttl' => 10, // Default 10 minutes ], ], ]; ``` -------------------------------- ### Generate filter classes with Artisan Source: https://context7.com/thavarshan/filterable/llms.txt Creates filter classes with optional model binding and feature toggles. Supports basic filter generation, model binding, minimal filters without features, and force overwriting existing filters. ```bash # Generate basic filter php artisan make:filter PostFilter # Generate filter with model binding php artisan make:filter PostFilter --model=Post # Generate minimal filter without features php artisan make:filter PostFilter --basic # Force overwrite existing filter php artisan make:filter PostFilter --force ``` -------------------------------- ### Constructing API Query Strings with JavaScript for Frontend Source: https://context7.com/thavarshan/filterable/llms.txt This JavaScript code demonstrates how to dynamically build URL query strings for API requests, supporting standard parameters and array/nested syntaxes compatible with backends like Laravel. It utilizes URLSearchParams for efficient parameter encoding. No external libraries are strictly required beyond standard browser Fetch API. ```javascript const fetchPosts = async (filters) => { const params = new URLSearchParams({ status: 'published', category_id: 5, published_after: '2025-01-01', q: 'laravel', per_page: 20 }); const response = await fetch(`/api/posts?${params.toString()}`); return response.json(); }; const fetchProductsWithTags = async () => { const params = new URLSearchParams(); params.append('tags[]', 'electronics'); params.append('tags[]', 'sale'); params.append('price_range[min]', '50'); params.append('price_range[max]', '500'); params.append('in_stock', 'true'); const response = await fetch(`/api/products?${params.toString()}`); return response.json(); }; // Curl examples // curl "https://api.example.com/posts?status=published&q=laravel&published_after=2025-01-01" // curl "https://api.example.com/products?tags[]=electronics&tags[]=sale&price_range[min]=50&price_range[max]=500" ``` -------------------------------- ### Enable or Disable Logging Globally in PHP Source: https://github.com/thavarshan/filterable/wiki/Filterable Toggle logging in the Filter class via static methods in a service provider. No additional dependencies beyond the Filter class. Inputs: boot method call; outputs: global logging state change. Useful for environment-specific control. ```php // AppServiceProvider.php /** * Bootstrap any application services. * * @return void */ public function boot(): void { // Enable logging globally through methods... Filter::enableLogging(); // or Disable logging globally through methods... Filter::disableLogging(); } ``` -------------------------------- ### Customizing Filter Configuration (PHP) Source: https://context7.com/thavarshan/filterable/llms.txt Demonstrates how to create a custom filter class, ConfiguredFilter, that extends the base Filter. It shows how to utilize package defaults and then selectively override them, such as disabling the global 'performance' feature while enabling 'caching' for this specific instance, and adjusting cache expiration and chunk size options. ```php disableFeature('performance'); // Turn off global default $this->enableFeature('caching'); // Add instance-specific feature $this->setCacheExpiration(5); // Override config TTL $this->setOption('chunk_size', 500); // Override config option } } ``` -------------------------------- ### Apply Pre-Filters in Laravel Controller Source: https://github.com/thavarshan/filterable/wiki/Filterable Illustrates how to apply pre-filters that execute before the main filtering logic. The `registerPreFilters` method accepts a closure that modifies the query builder, allowing for initial query constraints like filtering by a 'published' status. ```php use App\Models\Post; use App\Filters\PostFilter; use Illuminate\Http\Request; use Illuminate\Database\Eloquent\Builder; class PostController extends Controller { public function index(Request $request, PostFilter $filter) { $filter->registerPreFilters(function (Builder $query) { return $query->where('published', true); }); $query = Post::filter($filter); $posts = $request->has('paginate') ? $query->paginate($request->query('per_page', 20)) : $query->get(); return response()->json($posts); } } ``` -------------------------------- ### Manually Register FilterableServiceProvider Source: https://github.com/thavarshan/filterable/wiki/Filterable PHP code to manually register the FilterableServiceProvider in Laravel's config/app.php for versions that do not support package auto-discovery. ```php 'providers' => [ // Other service providers... Filterable\Providers\FilterableServiceProvider::class, ], ``` -------------------------------- ### Event Listeners for Lifecycle Hooks Source: https://context7.com/thavarshan/filterable/llms.txt This section explains how to subscribe to Filterable events to perform actions during the filter lifecycle, such as logging or triggering side effects. ```APIDOC ## Filterable Events ### Description The Filterable package fires events at various stages of the filtering process, allowing you to hook into these events for logging, debugging, or custom logic. ### Events - **FilterApplying** (`Filterable\Events\FilterApplying`): Dispatched before a filter is applied. - **FilterApplied** (`Filterable\Events\FilterApplied`): Dispatched after a filter has been successfully applied. - **FilterFailed** (`Filterable\Events\FilterFailed`): Dispatched when a filter fails to apply due to an error. ### Listener Example ```php get_class($event->filter), 'options' => $event->options, ]); } public function handleApplied(FilterApplied $event): void { Log::info('Filter applied successfully', [ 'filter' => get_class($event->filter), 'filters' => $event->filters, ]); } public function handleFailed(FilterFailed $event): void { Log::error('Filter failed', [ 'filter' => get_class($event->filter), 'error' => $event->exception->getMessage(), ]); } } ``` ### Registering Listeners in `EventServiceProvider.php` ```php [ \App\Listeners\LogFilterActivity::class.'@handleApplying', ], \Filterable\Events\FilterApplied::class => [ \App\Listeners\LogFilterActivity::class.'@handleApplied', ], \Filterable\Events\FilterFailed::class => [ \App\Listeners\LogFilterActivity::class.'@handleFailed', ], ]; // ... } ``` ``` -------------------------------- ### Create a Filter Class with Artisan Source: https://github.com/thavarshan/filterable/wiki/Filterable Artisan command to generate a new filter class in Laravel, which can be customized to add specific filter methods for models. ```bash php artisan make:filter PostFilter ``` -------------------------------- ### PHP EventFilter: Value Transformation and Pre-filters Source: https://context7.com/thavarshan/filterable/llms.txt Demonstrates how to configure an EventFilter in PHP to transform input data (like dates, tags, and prices) and apply global constraints before request-specific filters are processed. It includes validation rules and specific filter methods for date range, location, tags, and minimum price. ```php enableFeatures([ 'validation', 'valueTransformation', 'optimization', ]); // Transform date range from strings to Carbon instances $this->registerTransformer('date_range', function ($value) { if (!is_array($value)) { return $value; } return [ 'start' => isset($value['start']) ? Carbon::parse($value['start']) : null, 'end' => isset($value['end']) ? Carbon::parse($value['end']) : null, ]; }); // Transform comma-separated tags to array $this->registerTransformer('tags', function ($value) { return is_string($value) ? explode(',', $value) : $value; }); // Transform price string to float $this->registerTransformer('min_price', fn ($value) => (float) $value); // Apply global constraints before request filters $this->registerPreFilters(function (Builder $query) { $query->where('status', 'published') ->where('start_date', '>=', now()) ->whereNull('cancelled_at'); }); $this->setValidationRules([ 'date_range' => 'nullable|array', 'date_range.start' => 'nullable|date', 'date_range.end' => 'nullable|date|after:date_range.start', 'location' => 'nullable|string', 'tags' => 'nullable|array', 'min_price' => 'nullable|numeric|min:0', ]); } protected function dateRange(array $range): void { if (isset($range['start'])) { $this->getBuilder()->where('start_date', '>=', $range['start']); } if (isset($range['end'])) { $this->getBuilder()->where('end_date', '<=', $range['end']); } } protected function location(string $value): void { $this->getBuilder()->where('location', 'like', "%{$value}%"); } protected function tags(array $tags): void { $this->getBuilder()->whereHas('tags', function (Builder $query) use ($tags) { $query->whereIn('name', $tags); }); } protected function minPrice(float $price): void { $this->getBuilder()->where('price', '>=', $price); } } ``` -------------------------------- ### PHP UserExportService for Memory Management Source: https://context7.com/thavarshan/filterable/llms.txt Provides services for exporting user data to CSV and processing users in batches, with a focus on memory management for large datasets. It enables a 'memoryManagement' feature on a filter and uses methods like 'lazyEach', 'cursor', and 'reduce' to process data efficiently without loading everything into memory. ```php enableFeature('memoryManagement'); $filter->apply(User::query()); $path = 'exports/users-' . time() . '.csv'; $handle = fopen(Storage::path($path), 'w'); // Write CSV header fputcsv($handle, ['ID', 'Name', 'Email', 'Created At']); // Stream results in chunks $filter->lazyEach(function ($user) use ($handle) { fputcsv($handle, [ $user->id, $user->name, $user->email, $user->created_at->toDateString(), ]); }, 500); fclose($handle); return $path; } public function processUsersInBatches(UserFilter $filter): array { $filter->enableFeature('memoryManagement'); $filter->apply(User::query()); $stats = ['processed' => 0, 'updated' => 0, 'errors' => 0]; // Use cursor for minimal memory footprint foreach ($filter->cursor() as $user) { try { // Process user $user->last_processed_at = now(); $user->save(); $stats['updated']++; } catch (\Exception $e) { $stats['errors']++; } $stats['processed']++; } return $stats; } public function aggregateData(UserFilter $filter): array { $filter->enableFeature('memoryManagement'); $filter->apply(User::query()); // Reduce without loading all records return $filter->reduce(function ($carry, $user) { $carry['total']++; $carry['total_orders'] += $user->orders_count; $carry['total_revenue'] += $user->lifetime_value; return $carry; }, ['total' => 0, 'total_orders' => 0, 'total_revenue' => 0], 1000); } } ``` -------------------------------- ### Configure and Use Custom Laravel Logging Channel Source: https://github.com/thavarshan/filterable/wiki/Filterable Define a custom channel in Laravel's config/logging.php and retrieve it via Log facade for the Filter class. Depends on Laravel logging system. Inputs: config array with driver and path; outputs: channel-specific logger. Enables centralized configuration management. ```php // In config/logging.php 'channels' => [ 'filter' => [ 'driver' => 'single', 'path' => storage_path('logs/filter.log'), 'level' => 'debug', ], ], // Now, you can set this logger in your service provider or directly in your class using the `Log` facade: use Illuminate\Support\Facades\Log; // In your AppServiceProvider or wherever you set up the Filter class $filter->setLogger(Log::channel('filter')); ``` -------------------------------- ### Test Laravel Filters with PHPUnit Source: https://github.com/thavarshan/filterable/wiki/Filterable This PHPUnit test verifies that the PostFilter correctly filters Eloquent models by status. It creates test posts using Laravel factories, applies a filter via HTTP request parameters, and asserts that only matching posts are returned. Requires Laravel's testing framework, Eloquent models with factories, and a configured PostFilter class. ```php namespace Tests\Unit; use Tests\TestCase; use App\Models\Post; use App\Filters\PostFilter; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Http\Request; class PostFilterTest extends TestCase { use RefreshDatabase; public function testFiltersPostsByStatus(): void { $activePost = Post::factory()->create(['status' => 'active']); $inactivePost = Post::factory()->create(['status' => 'inactive']); $filter = new PostFilter(new Request(['status' => 'active'])); $filteredPosts = Post::filter($filter)->get(); $this->assertTrue($filteredPosts->contains($activePost)); $this->assertFalse($filteredPosts->contains($inactivePost)); } } ``` -------------------------------- ### PHP: Filter Chaining with Programmatic Constraints Source: https://context7.com/thavarshan/filterable/llms.txt Demonstrates how to chain request-driven filters with programmatic constraints in PHP. This allows combining filters defined in a Request with additional, hardcoded query conditions for more complex data retrieval. It utilizes a 'Filter' base class and Eloquent Builder for query construction. ```php enableFeatures([ 'validation', 'filterChaining', 'optimization', ]); $this->setValidationRules([ 'status' => 'nullable|in:pending,processing,completed,cancelled', 'customer_id' => 'nullable|integer', 'date_from' => 'nullable|date', ]); } protected function status(string $value): void { $this->getBuilder()->where('status', $value); } protected function customerId(int $id): void { $this->getBuilder()->where('customer_id', $id); } protected function dateFrom(string $date): void { $this->getBuilder()->whereDate('created_at', '>=', $date); } } // Controller usage with filter chaining class OrderController { public function index(Request $request, OrderFilter $filter) { $orders = Order::query() ->filter( $filter ->forUser($request->user()) // Add programmatic constraints after request filters ->where('total_amount', '>', 100) ->whereIn('payment_method', ['credit_card', 'paypal']) ->whereBetween('created_at', [ now()->subDays(30), now(), ]) ->orderBy('created_at', 'desc') ) ->paginate(25); return response()->json($orders); } } ``` -------------------------------- ### Advanced Caching with Smart Cache Keys in PHP Source: https://context7.com/thavarshan/filterable/llms.txt Configures the ProductFilter to enable advanced caching with deterministic keys based on filter values and user identity. It includes validation rules, caching expiration, and cache tags for efficient cache invalidation. Dependencies include Laravel's Cache facade and Request object. ```php enableFeatures(['validation', 'optimization']); $this->setCacheExpiration(15); // 15 minutes $this->cacheTags(['products', 'catalog']); // Redis/Memcached tags $this->setValidationRules([ 'category' => 'nullable|string', 'price_range' => 'nullable|array', 'price_range.min' => 'nullable|numeric|min:0', 'price_range.max' => 'nullable|numeric|gt:price_range.min', 'in_stock' => 'nullable|boolean', ]); } protected function category(string $value): void { $this->getBuilder()->whereHas('category', fn ($q) => $q->where('slug', $value)); } protected function priceRange(array $range): void { if (isset($range['min'])) { $this->getBuilder()->where('price', '>=', $range['min']); } if (isset($range['max'])) { $this->getBuilder()->where('price', '<=', $range['max']); } } protected function inStock(bool $value): void { if ($value) { $this->getBuilder()->where('stock_quantity', '>', 0); } } // Clear cache when products are updated public static function invalidateCache(): void { $filter = new static(request(), app(Cache::class)); $filter->clearRelatedCaches(['products', 'catalog']); } } ``` -------------------------------- ### Configure Filter Caching Globally Source: https://github.com/thavarshan/filterable/wiki/Filterable Demonstrates how to globally enable or disable caching for filters within a Laravel application. This is typically done in the `AppServiceProvider`. Use `Filter::enableCaching()` to turn caching on and `Filter::disableCaching()` to turn it off. ```php // AppServiceProvider.php /** * Bootstrap any application services. * * @return void */ public function boot(): void { // Enable caching globally through methods... Filter::enableCaching(); } ``` ```php // AppServiceProvider.php /** * Bootstrap any application services. * * @return void */ public function boot(): void { // Disable caching globally through methods... Filter::disableCaching(); } ``` -------------------------------- ### Laravel Event Listeners for Filter Lifecycle Hooks Source: https://context7.com/thavarshan/filterable/llms.txt This PHP code defines a Laravel listener to log events triggered by the Filterable package during the filter application process. It requires the Filterable package and Laravel's logging facilities. The listener handles 'applying', 'applied', and 'failed' events, logging relevant details such as the filter class, options, applied filters, and any exceptions encountered. ```php get_class($event->filter), 'options' => $event->options, ]); } public function handleApplied(FilterApplied $event): void { Log::info('Filter applied successfully', [ 'filter' => get_class($event->filter), 'filters' => $event->filters, ]); } public function handleFailed(FilterFailed $event): void { Log::error('Filter failed', [ 'filter' => get_class($event->filter), 'error' => $event->exception->getMessage(), ]); } } // EventServiceProvider.php protected $listen = [ \Filterable\Events\FilterApplying::class => [ \App\Listeners\LogFilterActivity::class.'@handleApplying', ], \Filterable\Events\FilterApplied::class => [ \App\Listeners\LogFilterActivity::class.'@handleApplied', ], \Filterable\Events\FilterFailed::class => [ \App\Listeners\LogFilterActivity::class.'@handleFailed', ], ]; ``` -------------------------------- ### PHP SearchFilter for Rate Limiting and Complexity Control Source: https://context7.com/thavarshan/filterable/llms.txt Implements rate limiting and query complexity control for search queries using a PHP filter. It defines filters, enables features like validation and rate limiting, sets maximum filters and complexity scores, and configures validation rules. It also includes methods to handle specific filters like 'q' and 'tags', and overrides rate limit behavior based on complexity. ```php enableFeatures([ 'validation', 'rateLimit', 'logging', 'performance', ]); // Rate limit configuration $this->setMaxFilters(5); $this->setMaxComplexity(50); $this->setFilterComplexity([ 'q' => 5, // Full-text search is expensive 'tags' => 3, // Array filters multiply by count 'categories' => 2, 'date_range' => 2, 'sort_by' => 1, ]); $this->setValidationRules([ 'q' => 'nullable|string|min:2|max:100', 'tags' => 'nullable|array|max:10', 'tags.*' => 'string', 'categories' => 'nullable|array|max:5', 'date_range' => 'nullable|array', ]); } protected function q(string $term): void { $this->getBuilder()->where(function (Builder $query) use ($term) { $query->where('title', 'like', "%{$term}%") ->orWhere('description', 'like', "%{$term}%") ->orWhere('content', 'like', "%{$term}%"); }); } protected function tags(array $tags): void { $this->getBuilder()->whereHas('tags', function (Builder $query) use ($tags) { $query->whereIn('tags.slug', $tags); }, '>=', count($tags)); } // Override rate limit window for high-complexity queries protected function resolveRateLimitWindowSeconds(int $complexityScore): int { return $complexityScore > 30 ? 120 : 60; } // Adjust decay based on complexity protected function resolveRateLimitDecaySeconds(int $complexityScore): int { return max(5, (int) ceil($complexityScore / 5)); } } ``` -------------------------------- ### PHP: Permission-Based Filtering Source: https://context7.com/thavarshan/filterable/llms.txt Illustrates how to implement permission-based filtering in PHP, restricting access to specific filters based on user abilities. This enhances security by ensuring only authorized users can apply certain data filters. It integrates with authorization systems like Laravel's Gate. ```php enableFeatures([ 'validation', 'permissions', 'logging', ]); // Define which abilities are required for each filter $this->setFilterPermissions([ 'email' => 'users.search', 'role' => 'users.filter-by-role', 'status' => 'users.filter-by-status', 'created_after' => 'users.view-all', ]); $this->setValidationRules([ 'email' => 'nullable|email', 'role' => 'nullable|in:admin,moderator,user', 'status' => 'nullable|in:active,suspended,banned', 'created_after' => 'nullable|date', ]); } protected function email(string $value): void { $this->getBuilder()->where('email', 'like', "%{$value}%"); } protected function role(string $value): void { $this->getBuilder()->whereHas('roles', fn ($q) => $q->where('name', $value)); } protected function status(string $value): void { $this->getBuilder()->where('status', $value); } protected function createdAfter(string $date): void { $this->getBuilder()->whereDate('created_at', '>=', $date); } // Integrate with Laravel's Gate or custom authorization protected function userHasPermission(string $ability, mixed $user): bool { if (!$user) { return false; } // Use Laravel Gate return \Illuminate\Support\Facades\Gate::forUser($user)->allows($ability); // Or custom permission system // return $user->hasPermission($ability); } } ``` -------------------------------- ### Generate a filter class in Laravel Source: https://github.com/thavarshan/filterable/blob/main/README.md Creates a new filter class for a specified Eloquent model using Artisan. Options include wiring to a model, creating a basic shell, or forcing overwrite of existing classes. ```bash php artisan make:filter PostFilter --model=Post ``` -------------------------------- ### Add Filterable trait to Eloquent models Source: https://context7.com/thavarshan/filterable/llms.txt Shows how to integrate the Filterable trait into Eloquent models to enable scope-based filtering. Includes model definition with fillable attributes, casts, and relationships. ```php 'datetime', 'is_visible' => 'boolean', ]; public function author(): BelongsTo { return $this->belongsTo(User::class, 'user_id'); } public function category(): BelongsTo { return $this->belongsTo(Category::class); } } ``` -------------------------------- ### Controller Usage with Filter Pipeline in PHP Source: https://context7.com/thavarshan/filterable/llms.txt Applies filters to Post queries with optional caching, user scoping, and memory management. It leverages the PostFilter class to dynamically build query constraints and paginate results. Dependencies include Laravel's Eloquent models and the PostFilter class. ```php filter( $filter ->forUser($request->user()) ->enableFeature('caching') ->setCacheExpiration(10) ->setOptions(['chunk_size' => 500]) ) ->paginate($request->integer('per_page', 15)); return PostResource::collection($posts); } public function indexWithMemoryManagement(Request $request, PostFilter $filter) { $filter->enableFeature('memoryManagement'); $filter->apply(Post::query()); // Stream results without loading all into memory return $filter->lazy(1000)->map(fn ($post) => [ 'id' => $post->id, 'title' => $post->title, 'status' => $post->status, ]); } } ``` -------------------------------- ### Apply User-Scoped Filters in Laravel Controller Source: https://github.com/thavarshan/filterable/wiki/Filterable Shows how to apply filters scoped to the currently authenticated user. The `forUser` method on the filter instance is used to set the user context before applying filters to the query. This ensures filters are relevant to the logged-in user. ```php use App\Models\Post; use App\Filters\PostFilter; use Illuminate\Http\Request; class PostController extends Controller { public function index(Request $request, PostFilter $filter) { $filter->forUser($request->user()); $query = Post::filter($filter); $posts = $request->has('paginate') ? $query->paginate($request->query('per_page', 20)) : $query->get(); return response()->json($posts); } } ```