Relayphp/relay是符合PSR-15、持续维护且被Slim/Swoole等框架间接采用的中间件调度器,需通过composer require relayphp/relay安装,其Relay\Relay类负责构建中间件链,要求每个中间件必须实现MiddlewareInterface、显式调用$handler->handle($request)并返回ResponseInterface实例,否则流程短路或触发TypeError。

Composer 能直接安装 PHP-Middleware 库,但默认不提供 PSR-15 兼容的中间件执行器 —— 你得自己搭链式调用或选配兼容实现。
确认你要用的是哪个 php-middleware 库
GitHub 上搜 php-middleware 会出来多个不同作者的库,最常被误用的是 oscarotero/middleland(已归档)和 relayphp/relay。真正符合 PSR-15、持续维护且被 Slim/Swoole 等框架间接采用的是 relayphp/relay。
别装错包:
- 错误: composer require php-middleware/php-middleware(这个包早已废弃,无 PSR-15 支持)
- 正确: composer require relayphp/relay
装完后,Relay\Relay 类就是你的 PSR-15 兼容中间件调度器。
用 Relay\Relay 构建中间件链时必须传入 ServerRequestInterface 和 ResponseInterface
PSR-15 要求每个中间件必须是 callable 或实现 MiddlewareInterface,且签名固定为:function (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface。
立即学习“PHP免费学习笔记(深入)”;
常见错误是漏传 $handler 或返回值类型不对 —— Relay 不会帮你兜底,PHP 会直接报 Fatal error: Uncaught TypeError。
实操要点:
- 所有中间件必须返回
ResponseInterface实例,不能 return null 或 echo 输出 - 调用下游必须显式执行
$handler->handle($request),不能只写$handler($request)(后者不满足 PSR-15) - 建议用
zendframework/zend-diactoros提供请求/响应实例:composer require zendframework/zend-diactoros
中间件顺序和短路逻辑容易被忽略
Relay 按数组顺序执行中间件,但一旦某个中间件没调用 $handler->handle($request),后续中间件就彻底跳过 —— 这是设计使然,不是 bug。
典型场景如鉴权中间件:
function ($request, $handler) {
if (! $request->getAttribute('auth')) {
return new JsonResponse(['error' => 'Unauthorized'], 401);
}
return $handler->handle($request); // ← 忘了这行,后面所有中间件都不执行
}调试时如果发现某段逻辑“突然没了”,先检查是不是前面某个中间件提前 return 且没调 $handler->handle()。
别指望 relayphp/relay 自带路由或请求解析
它只做一件事:按序调用中间件并传递请求/响应对象。没有 URL 匹配、没有参数解析、不读 $_GET 或 $_POST。
你要组合使用:
- 路由:
nikic/fast-route或slim/slim(Slim 4+ 本身基于 Relay) - 请求体解析:自己用
json_decode(file_get_contents('php://input')),或加nyholm/psr7+http-interop/http-middleware-handler - 错误处理:需手动 wrap
try/catch在首层中间件里,Relay 不捕获异常
PSR-15 是契约,不是框架 —— Relay 是最薄的一层胶水,粘什么、怎么粘,全由你决定。



















