1. Go to this page and download the library: Download jerome/filterable library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
jerome / filterable example snippets
'providers' => [
// Other service providers...
Filterable\Providers\FilterableServiceProvider::class,
],
namespace App\Filters;
use Filterable\Filter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Contracts\Cache\Repository as Cache;
use Psr\Log\LoggerInterface;
class PostFilter extends Filter
{
protected array $filters = ['status', 'category'];
/**
* Enable specific features for this filter.
*/
public function __construct(Request $request, ?Cache $cache = null, ?LoggerInterface $logger = null)
{
parent::__construct($request, $cache, $logger);
// Enable the features you need
$this->enableFeatures([
'validation',
'caching',
'logging',
'performance',
]);
}
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);
}
}
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;
}
use App\Models\Post;
use App\Filters\PostFilter;
$filter = new PostFilter(request(), cache(), logger());
$posts = Post::filter($filter)->get();
use App\Models\Post;
use App\Filters\PostFilter;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index(Request $request, PostFilter $filter)
{
$query = Post::filter($filter);
$posts = $request->has('paginate')
? $query->paginate($request->query('per_page', 20))
: $query->get();
return response()->json($posts);
}
}
return [
// Other service providers...
Filterable\Providers\FilterableServiceProvider::class,
];
namespace App\Http\Controllers;
use App\Models\Post;
use App\Filters\PostFilter;
use Illuminate\Http\Request;
class PostIndexController extends Controller
{
public function __invoke(Request $request, PostFilter $filter)
{
$query = Post::filter($filter);
$posts = $request->has('paginate')
? $query->paginate($request->query('per_page', 20))
: $query->get();
return response()->json($posts);
}
}
use App\Http\Controllers\PostIndexController;
Route::get('/posts', PostIndexController::class);
// Enable individual features
$filter->enableFeature('validation');
$filter->enableFeature('caching');
// Enable multiple features at once
$filter->enableFeatures([
'validation',
'caching',
'logging',
'performance',
]);
// Disable a feature
$filter->disableFeature('caching');
// Check if a feature is enabled
if ($filter->hasFeature('caching')) {
// Do something
}
// Enable all features
$filter->enableFeatures([
'validation',
'permissions',
'rateLimit',
'caching',
'logging',
'performance',
'optimization',
'memoryManagement',
'filterChaining',
'valueTransformation',
]);
$filter->setValidationRules([
'status' => ':categories,id',
]);
// Add custom validation messages
$filter->setValidationMessages([
'status.in' => 'Status must be either active or inactive',
]);
$filter->setFilterPermissions([
'admin_only_filter' => 'admin',
'editor_filter' => ['editor', 'admin'],
]);
// Implement the permission check in your filter class
protected function userHasPermission(string|array $permission): bool
{
if (is_array($permission)) {
return collect($permission)->contains(fn ($role) => $this->forUser->hasRole($role));
}
return $this->forUser->hasRole($permission);
}
// Set the maximum number of filters that can be applied at once
$filter->setMaxFilters(10);
// Set the maximum complexity score for all filters combined
$filter->setMaxComplexity(100);
// Define complexity scores for specific filters
$filter->setFilterComplexity([
'complex_filter' => 10,
'simple_filter' => 1,
]);
// Process a query with lazy loading
$posts = $filter->lazy()->each(function ($post) {
// Process each post with minimal memory usage
});
// Use chunking for large datasets
$filter->chunk(1000, function ($posts) {
// Process posts in chunks of 1000
});
// Map over query results without loading all records
$result = $filter->map(function ($post) {
return $post->title;
});
// Filter results without loading all records
$result = $filter->filter(function ($post) {
return $post->status === 'active';
});
// Reduce results without loading all records
$total = $filter->reduce(function ($carry, $post) {
return $carry + $post->views;
}, 0);
// Get a lazy collection with custom chunk size
$lazyCollection = $filter->lazy(500);
// Process each item with minimal memory usage
$filter->lazyEach(function ($item) {
// Process item
}, 500);
// Create a generator to iterate with minimal memory
foreach ($filter->cursor() as $item) {
// Process item
}
// Select only needed columns
$filter->select(['id', 'title', 'status']);
// Eager load relationships
$filter->with(['author', 'comments']);
// Set chunk size for large datasets
$filter->chunkSize(1000);
// Use a database index hint
$filter->useIndex('idx_posts_status');
// Set cache expiration time (in minutes)
$filter->setCacheExpiration(60);
// Manually clear the cache
$filter->clearCache();
// Use tagged cache for better invalidation
$filter->cacheTags(['posts', 'api']);
// Enable specific caching modes
$filter->cacheResults(true);
$filter->cacheCount(true);
// Get the number of items with caching
$count = $filter->count();
// Clear related caches when models change
$filter->clearRelatedCaches(Post::class);
// Get SQL query without executing it
$sql = $filter->toSql();
// Set a custom logger
$filter->setLogger($customLogger);
// Get the current logger
$logger = $filter->getLogger();
// Log at different levels
$filter->logInfo("Applying filter", ['filter' => 'status']);
$filter->logDebug("Filter details", ['value' => $value]);
$filter->logWarning("Potential issue", ['problem' => 'description']);
// Logging is automatically handled if enabled
// You can also add custom logging in your filter methods:
protected function customFilter($value): Builder
{
$this->logInfo("Applying custom filter with value: {$value}");
return $this->builder->where('custom_field', $value);
}
// Get performance metrics after applying filters
$metrics = $filter->getMetrics();
// Add custom metrics
$filter->addMetric('custom_metric', $value);
// Get execution time
$executionTime = $filter->getExecutionTime();
// Register a transformer for a filter
$filter->registerTransformer('date', function ($value) {
return Carbon::parse($value)->toDateTimeString();
});
// Register a transformer for an array of values
$arrayTransformer = function($values) {
return array_map(fn($value) => strtolower($value), $values);
};
$filter->registerTransformer('tags', $arrayTransformer);
// Only apply a filter if a condition is met
$filter->when($request->has('status'), function ($filter) use ($request) {
$filter->where('status', $request->status);
});
// Apply one filter or another based on a condition
$filter->when($request->has('sort'),
function ($filter) use ($request) {
$filter->orderBy($request->sort);
},
function ($filter) {
$filter->orderBy('created_at', 'desc');
}
);
// Check the current state
if ($filter->getDebugInfo()['state'] === 'applied') {
// Process results
}
// Reset the filter to its initial state
$filter->reset();
$debugInfo = $filter->getDebugInfo();
// Debug info features
// - Query options
// - SQL query and bindings
// - Performance metrics (if enabled)
class MyFilter extends Filter
{
protected function handleFilteringException(Throwable $exception): void
{
// Log the exception
$this->logWarning('Filter exception', [
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
]);
// Optionally rethrow specific exceptions
if ($exception instanceof MyCustomException) {
throw $exception;
}
// Otherwise, let the parent handle it
parent::handleFilteringException($exception);
}
}
use App\Models\Post;
use App\Filters\PostFilter;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index(Request $request, PostFilter $filter)
{
// Enable features
$filter->enableFeatures([
'validation',
'caching',
'logging',
'performance',
]);
// Set validation rules
$filter->setValidationRules([
'status' => 'sometimes|in:active,inactive',
'category_id' => 'sometimes|integer|exists:categories,id',
]);
// Apply user scope
$filter->forUser($request->user());
// Apply pre-filters
$filter->registerPreFilters(function ($query) {
return $query->where('published', true);
});
// Set caching options
$filter->setCacheExpiration(30);
$filter->cacheTags(['posts', 'api']);
// Apply custom filter chain
$filter->where('is_featured', true)
->orderBy('created_at', 'desc');
// Apply filters to the query
$query = Post::filter($filter);
// Get paginated results
$posts = $request->has('paginate')
? $query->paginate($request->query('per_page', 20))
: $query->get();
// Get performance metrics if needed
$metrics = null;
if ($filter->hasFeature('performance')) {
$metrics = $filter->getMetrics();
}
return response()->json([
'data' => $posts,
'metrics' => $metrics,
]);
}
}
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));
}
public function testRateLimitingRejectsComplexQueries(): void
{
// Create a filter with too many parameters
$filter = new PostFilter(new Request([
'param1' => 'value1',
'param2' => 'value2',
// ... many more parameters
]));
$filter->enableFeature('rateLimit');
$filter->setMaxFilters(5);
// Apply the filter and check if rate limiting was triggered
$result = Post::filter($filter)->get();
// Assert that no results were returned due to rate limiting
$this->assertEmpty($result);
}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.