Closure, Middleware, GroupMiddleware) can be bridged via HTTP Interop adapters (e.g., zend-stratigility or laminas/laminas-http-handler-runner), though this introduces abstraction overhead.Psr\Http\Message\ResponseInterface/RequestInterface).$middlewarePriority may conflict with dynamic dispatch order.Psr\Http\Message objects in Laravel tests may require additional tooling (e.g., php-http/mock-client).| Risk Area | Severity | Mitigation Strategy |
|---|---|---|
| PSR-15/Laravel Bridge | High | Develop a lightweight adapter layer (e.g., LaravelMiddlewareToPsr15). |
| Middleware Ordering | Medium | Document priority rules and provide a MiddlewareDispatcher facade for explicit control. |
| Performance Overhead | Low | Benchmark PSR-15 dispatch vs. native Laravel middleware (expect minimal impact). |
| Dependency Bloat | Low | Use composer require only for PSR-15 adapters (e.g., laminas/laminas-diactoros). |
| License Compliance | Low | MIT license is compatible; no conflicts with Laravel’s MIT license. |
Request/Response objects (e.g., adding headers, rewriting URLs)?RequestHandlerInterface failures) translated to Laravel’s error responses?Middleware::when() or Middleware::prepend() achieve similar goals without PSR-15?$middleware array, Kernel.php, or service provider bindings.nyholm/psr7, laminas/laminas-diactoros) to bridge Laravel’s Illuminate\Http\Request/Response with Psr\Http\Message.// composer.json
{
"require": {
"laminas/laminas-diactoros": "^2.10", // PSR-7 implementation
"equip/dispatch": "^1.0", // The middleware dispatcher
"php-http/message-factory": "^1.0" // Optional: for PSR-7 factory
}
}
Phase 1: Proof of Concept
// app/Middleware/Psr15Adapter.php
namespace App\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class Psr15Adapter implements \Psr\Http\Server\MiddlewareInterface {
public function __construct(private \Closure $laravelMiddleware) {}
public function process(ServerRequestInterface $request, \Psr\Http\Server\RequestHandlerInterface $handler): ResponseInterface {
$laravelRequest = Request::createFromBase($request);
$laravelResponse = $this->laravelMiddleware($laravelRequest);
return new \Laminas\Diactoros\Response($laravelResponse->getStatusCode(), [], $laravelResponse->getContent());
}
}
Phase 2: Dispatcher Integration
// app/Providers/AppServiceProvider.php
public function register() {
$this->app->singleton(\Equip\Dispatch\MiddlewareDispatcher::class, function ($app) {
return new \Equip\Dispatch\MiddlewareDispatcher(
new \Laminas\Diactoros\ServerRequestFactory(),
new \Laminas\Diactoros\ResponseFactory()
);
});
}
// app/Helpers/MiddlewareDispatcher.php
use Equip\Dispatch\MiddlewareDispatcher;
use Illuminate\Support\Facades\Facade;
class MiddlewareDispatcherFacade extends Facade {
protected static function getFacadeAccessor() { return MiddlewareDispatcher::class; }
}
Phase 3: Route-Level Integration
Kernel.php or route middleware:
// routes/web.php
Route::get('/dynamic-middleware', function () {
return response()->json(['message' => 'Success']);
})->middleware(function ($request, $next) {
$dispatcher = app(MiddlewareDispatcher::class);
$psrRequest = \Laminas\Diactoros\ServerRequestFactory::fromGlobals();
$psrResponse = $dispatcher->dispatch($psrRequest, new class implements \Psr\Http\Server\RequestHandlerInterface {
public function handle(\Psr\Http\Message\ServerRequestInterface $request): \Psr\Http\Message\ResponseInterface {
return new \Laminas\Diactoros\Response();
}
});
return new Response($psrResponse->getBody(), $psrResponse->getStatusCode());
});
symfony/http-foundation) reduces adapter complexity.Illuminate dependencies (e.g., Authenticate, VerifyCsrfToken) unless wrapped.$next pattern.How can I help you explore Laravel packages today?