Filterable
Home
📦 Installation
  • Setting Up Filterable
  • Discover Command
  • Listing All Filters
  • Testing Filters
  • Inspecting Filterable Classes
GitHub
Home
📦 Installation
  • Setting Up Filterable
  • Discover Command
  • Listing All Filters
  • Testing Filters
  • Inspecting Filterable Classes
GitHub
  • Home
  • Introduction
  • Installation
  • Service Provider
  • How It Works
  • Engines

    • Invokable
    • Tree
    • Ruleset
    • Expression
  • Features

    • Header-Driven Filter Mode
    • Auto Register Filterable Macro
    • Conditional Logic
    • Filter Aliases
    • Through callbacks
    • Auto Binding
    • Custom engines
    • Data Provisioning
  • Execution

    • Invoker
  • API

    • Filterable
    • Filterable facade
    • Payload
    • Sorter
  • CLI

    • Setup Filterable
    • Discover Filters
    • Test Filter
    • List Filters
    • Inspect Filter
  • Event System
  • Profile Management
  • Profiler
  • Sorting
  • Authorization
  • Validation
  • Sanitization

Filterable Service Provider Overview

This guide demonstrates how to use the FilterableServiceProvider in a Laravel application.

Publishing Assets

# Publish only configuration
php artisan vendor:publish --tag=filterable-config

# Publish only stubs
php artisan vendor:publish --tag=filterable-stubs

# Publish all filterable assets
php artisan vendor:publish --tag=filterable

Service Resolution

// Via Facade (requires facade registration)
use Filterable;

$filterable = Filterable::create();

// Via Container
$filterable = app('filterable');

// Via Dependency Injection
public function index(Filterable $filterable)
{
    return $filterable->setModel(User::class)->apply();
}

// Via Manual Resolution
$filterable = app(Filterable::class);

Advanced Customization

Creating an Extended Service Provider

Create app/Providers/CustomFilterableServiceProvider.php:

<?php

namespace App\Providers;

use Kettasoft\Filterable\Providers\FilterableServiceProvider;
use Kettasoft\Filterable\Engines\Factory\EngineManager;
use App\Filters\Engines\GraphQLEngine;
use App\Filters\Sanitizers\SqlInjectionSanitizer;
use App\Http\Middleware\FilterableAuthMiddleware;

class CustomFilterableServiceProvider extends FilterableServiceProvider
{
    /**
     * Register custom filtering engines.
     */
    protected function registerCustomEngines(): void
    {
        // Register a GraphQL-compatible engine
        EngineManager::extend('graphql', GraphQLEngine::class);
        EngineManager::extend('custom', CustomEngine::class);
    }

    /**
     * Register custom sanitizers.
     */
    protected function registerCustomSanitizers(): void
    {
        // Register additional security sanitizers
        $this->app->bind('filterable.sanitizer.sql_injection', SqlInjectionSanitizer::class);

        // Register in sanitizer registry if using a registry pattern
        $this->app->make('filterable.sanitizer.registry')
            ->register('sql_injection', SqlInjectionSanitizer::class);
    }

    /**
     * Register additional services.
     */
    protected function registerAdditionalServices(): void
    {
        // Custom field resolver for dynamic schema
        $this->app->singleton('filterable.field_resolver', function ($app) {
            return new DynamicFieldResolver(
                $app['db'],
                $app['cache.store']
            );
        });

        // Custom authorization service
        $this->app->singleton('filterable.authorizer', function ($app) {
            return new FilterableAuthorizer(
                $app['auth'],
                $app['gate']
            );
        });
    }

    /**
     * Boot customizations.
     */
    protected function bootCustomizations(): void
    {
        // Register custom macros
        Filterable::macro('withDynamicFields', function () {
            $resolver = app('filterable.field_resolver');
            $fields = $resolver->resolveForModel($this->getModel());
            return $this->setAllowedFields($fields);
        });

        // Configure custom engines based on environment
        if (config('app.env') === 'testing') {
            // Use a mock engine for testing
            $this->app->singleton('filterable.engine.mock', MockEngine::class);
        }
    }

    /**
     * Register middleware.
     */
    protected function registerMiddleware(): void
    {
        $router = $this->app['router'];

        // Register authorization middleware
        $router->aliasMiddleware('filterable.auth', FilterableAuthMiddleware::class);

        // Register rate limiting middleware
        $router->aliasMiddleware('filterable.throttle', FilterableThrottleMiddleware::class);
    }

    /**
     * Register event listeners.
     */
    protected function registerEventListeners(): void
    {
        // Listen to filterable events for logging/monitoring
        Event::listen('filterable.query.executed', function ($event) {
            Log::info('Filterable query executed', [
                'model' => $event->model,
                'filters' => $event->filters,
                'execution_time' => $event->executionTime,
            ]);
        });

        // Listen for security events
        Event::listen('filterable.security.violation', function ($event) {
            Log::warning('Filterable security violation detected', [
                'ip' => request()->ip(),
                'filters' => $event->filters,
                'violation' => $event->violation,
            ]);
        });
    }
}

Update config/app.php

Replace the original service provider:

'providers' => [
    // Remove this line:
    // Kettasoft\Filterable\Providers\FilterableServiceProvider::class,

    // Add this line:
    App\Providers\CustomFilterableServiceProvider::class,
],

Configuration Examples

Environment-Specific Configuration

# .env
FILTERABLE_PROFILER_ENABLED=true
FILTERABLE_PROFILER_STORE=log
FILTERABLE_PROFILER_THRESHOLD=500

# .env.testing
FILTERABLE_PROFILER_ENABLED=false
FILTERABLE_ENGINE_DEFAULT=mock

Performance Considerations

Caching Dynamic Fields

protected function registerAdditionalServices(): void
{
    $this->app->singleton('filterable.field_resolver', function ($app) {
        return new CachedFieldResolver(
            new DynamicFieldResolver($app['db']),
            $app['cache.store'],
            3600 // Cache for 1 hour
        );
    });
}

Lazy Loading Engines

protected function registerCustomEngines(): void
{
    $this->app->singleton('filterable.engine.heavy', function ($app) {
        // Only instantiate when actually needed
        return new HeavyProcessingEngine(
            $app['config']['filterable.heavy_engine']
        );
    });
}

Monitoring and Debugging

Enable Detailed Logging

protected function registerEventListeners(): void
{
    if (config('app.debug')) {
        Event::listen('filterable.*', function ($event, $data) {
            Log::debug('Filterable event', [
                'event' => $event,
                'data' => $data,
                'memory' => memory_get_usage(true),
                'time' => microtime(true),
            ]);
        });
    }
}

Custom Profiler Storage

protected function registerAdditionalServices(): void
{
    $this->app->bind(ProfilerStorageContract::class, function ($app) {
        $driver = config('filterable.profiler.store');

        return match ($driver) {
            'database' => new DatabaseProfilerStorage(),
            'log' => new FileProfilerStorage(),
            'redis' => new RedisProfilerStorage($app['redis']),
            default => throw new InvalidArgumentException("Unsupported driver: {$driver}")
        };
    });
}

This service provider provides a solid foundation for building robust, maintainable, and extensible filtering functionality in Laravel applications.

Edit this page
Last Updated:
Contributors: kettasoft
Prev
Installation
Next
How It Works