mindplay/middleman
PSR-15 middleware dispatcher for PHP that composes middleware into a single request handler. Supports lazy middleware resolution from a PSR-11 container, class-name based middleware, and PSR-7/PSR-15 stacks, making it easy to build clean, layered HTTP applications.
Architecture fit
mindplay/middleman is a generic PSR-15 MiddlewareInterface / PSR-7 dispatcher: it resolves middleware from a PSR-11 container, chains them via RequestHandler delegates, and returns a PSR-7 ResponseInterface. It has no Laravel awareness — no service provider, no facade, no HTTP-kernel hook, no config.Illuminate\Pipeline\Pipeline driven by Illuminate\Foundation\Http\Kernel, with its own contracts (handle($request, Closure $next)), middleware groups, priority ordering, terminable middleware, and Request/Response subclasses. Those are not PSR-15/PSR-7. Adopting Middleman means running a second, parallel middleware engine rather than extending the existing one.app/Http/Middleware work, Middleman is an impedance mismatch with no functional gain over the framework pipeline.Integration feasibility
symfony/psr-http-message-bridge + a PSR-7/PSR-17 implementation (nyholm/psr7 or guzzlehttp/psr7) to convert Laravel's Request inbound and PSR-7 Response outbound. Every request pays a conversion cost and body re-buffering.ContainerMiddlewareResolver can be pointed at it directly — that part is clean. Attribute-based resolution, tagged middleware, and per-route middleware aliases would all need hand-rolled glue.Technical risk
terminate() calls, $next($request) short-circuiting, and exception-to-response mapping have no direct PSR-15 equivalent. Behavior will differ subtly, and auth/session/CSRF middleware cannot be reused across the boundary.Illuminate\Pipeline, league/route, Laminas Stratigility, or Slim's dispatcher. We would be taking on a dependency to solve a problem Laravel already solves.Key questions
BinaryFileResponse? Bridging these through PSR-7 is where conversions break.Stack fit
MiddlewareInterface stack and is invoked from one Laravel route.Route::any('/psr/{path?}', PsrBridgeController::class)->where('path', '.*') → convert Illuminate\Http\Request to PSR-7 → run Middleman with our middleware list → convert PSR-7 response back to Illuminate\Http\Response.Migration path
PsrMiddlewareRunner) so the vendor dependency is swappable for Illuminate\Pipeline or a fork without touching call sites.app/Http/Middleware moves.Compatibility
composer.json conflict/allowlist and an automated composer outdated + PHP matrix check so an abandoned upstream is a known state rather than a surprise.nyholm/psr7 is the lighter default.Sequencing
Maintenance
Support
Scaling
Failure modes
Content-Length, Transfer-Encoding, and Set-Cookie can be dropped or reordered.get() semantics differ from Laravel's autowiring and contextual binding; middleware depending on request-scoped bindings can resolve stale or fail.Ramp-up
MiddlewareDispatcher, MiddlewareResolver, Delegate) and can be learned in under a day by anyone comfortable with PSR-7.$next(), and the absence of framework conveniences. Plan a short internal walkthrough and a reference example in the repo before the first adopter outside the seam.How can I help you explore Laravel packages today?