Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Callable Handler Laravel Package

tuupola/callable-handler

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require tuupola/callable-handler
    

    Add to composer.json if not using autoload:

    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    }
    
  2. First Use Case: Convert a PSR-7 middleware (e.g., Middleware\ExampleMiddleware) to work with PSR-15 by wrapping it:

    use Tuupola\CallableHandler\CallableHandler;
    
    $handler = new CallableHandler();
    $middleware = $handler->wrap($this->middleware); // $this->middleware is PSR-7
    
  3. Quick Integration with Laravel: In app/Http/Kernel.php, replace PSR-7 middleware with PSR-15 equivalents:

    protected $middleware = [
        \Tuupola\CallableHandler\CallableHandler::class . ':wrap',
        \App\Http\Middleware\ExampleMiddleware::class,
    ];
    

Implementation Patterns

Core Workflows

  1. PSR-7 to PSR-15 Conversion: Use CallableHandler to wrap legacy PSR-7 middleware for PSR-15 compatibility:

    $handler = new CallableHandler();
    $psr15Middleware = $handler->wrap($psr7Middleware);
    
  2. Double-Pass Middleware: Implement __invoke() with the DoublePassTrait for middleware requiring two passes (e.g., auth + CORS):

    use Tuupola\CallableHandler\DoublePassTrait;
    
    class AuthMiddleware
    {
        use DoublePassTrait;
    
        public function __invoke($request, $handler)
        {
            // First pass logic
            return $handler($request)->then(...);
        }
    }
    
  3. Laravel Middleware Integration: Extend Laravel’s middleware stack by wrapping PSR-7 middleware in Handle:

    namespace App\Http\Middleware;
    
    use Tuupola\CallableHandler\CallableHandler;
    
    class ConvertMiddleware
    {
        public function __construct(CallableHandler $handler)
        {
            $this->handler = $handler;
        }
    
        public function handle($request, Closure $next)
        {
            $psr15Middleware = $this->handler->wrap($request->middleware());
            return $psr15Middleware($request, $next);
        }
    }
    
  4. Grouped Middleware Handling: Process groups of middleware (e.g., middlewareGroups in Laravel) by wrapping each:

    $groupedMiddleware = collect($middlewareGroups['web'])
        ->map(fn($middleware) => $handler->wrap($middleware))
        ->all();
    

Integration Tips

  • PSR-15 Router Integration: Use with frameworks like slim/slim or zend-expressive by registering wrapped middleware:

    $app->pipe($handler->wrap($psr7Middleware));
    
  • Dependency Injection: Bind CallableHandler in Laravel’s service container:

    $app->singleton(CallableHandler::class, fn() => new CallableHandler());
    
  • Testing: Mock CallableHandler in tests to verify middleware behavior:

    $handler = $this->createMock(CallableHandler::class);
    $handler->method('wrap')->willReturn($psr15Middleware);
    

Gotchas and Tips

Pitfalls

  1. Double-Pass Misuse: Avoid using DoublePassTrait for single-pass middleware—it adds unnecessary complexity and may break PSR-15 compliance. Fix: Use CallableHandler::wrap() for single-pass conversions.

  2. PHP Version Conflicts: Ensure PHP ≥7.1 (min) or ≥8.0 (for newer features). Older versions may fail silently. Fix: Update composer.json constraints or use ^1.1.0 for PHP 8 support.

  3. Middleware Ordering: Wrapping middleware changes execution order. Test thoroughly after conversion. Fix: Log middleware stack or use tap() to debug:

    $middleware = $handler->wrap($middleware)->tap(fn($m) => logger()->debug($m));
    
  4. PSR-7 vs. PSR-15 Signature: PSR-7 middleware expects $request, $response, $next, while PSR-15 uses $request, $handler. Fix: Use CallableHandler to auto-adapt signatures.


Debugging

  • Enable Error Logging: Configure CallableHandler to log wrapped calls:

    $handler = new CallableHandler();
    $handler->setLogger(new \Monolog\Logger('middleware'));
    
  • Check Return Types: Ensure middleware returns ResponseInterface (PSR-7) or PromiseInterface (PSR-15). Use:

    if (!$response instanceof \Psr\Http\Message\ResponseInterface) {
        throw new \RuntimeException('Invalid response type');
    }
    

Extension Points

  1. Custom Wrappers: Extend CallableHandler to support additional middleware types:

    class CustomHandler extends CallableHandler
    {
        public function wrapCustom($middleware)
        {
            return fn($request, $handler) => $middleware($request, $handler, 'custom');
        }
    }
    
  2. Middleware Metadata: Add metadata (e.g., tags) to wrapped middleware:

    $wrapped = $handler->wrap($middleware);
    $wrapped->setMetadata(['tag' => 'auth']);
    
  3. Performance Optimization: Cache wrapped middleware instances for repeated use:

    static $cache = [];
    $wrapped = $cache[$middleware::class] ??= $handler->wrap($middleware);
    

Config Quirks

  • Laravel Caching: If using Laravel’s middleware caching (php artisan cache:clear), clear the CallableHandler cache manually:

    $handler->clearCache();
    
  • PSR-15 Middleware Groups: Laravel’s middlewareGroups may not auto-wrap PSR-7 middleware. Manually wrap in Kernel.php:

    $middleware = collect($this->middlewareGroups['web'])
        ->map(fn($m) => $handler->wrap($m))
        ->all();
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor