Weave 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.
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support