
本文详解如何将 Slim 3 中依赖 $next 调用的传统中间件,重构为符合 Slim 4 PSR-15 规范的 RequestHandler 风格中间件,包括参数签名变更、响应返回逻辑重写及 JWT 权限校验的适配要点。
本文详解如何将 slim 3 中依赖 `$next` 调用的传统中间件,重构为符合 slim 4 psr-15 规范的 `requesthandler` 风格中间件,包括参数签名变更、响应返回逻辑重写及 jwt 权限校验的适配要点。
Slim 4 对中间件的设计进行了重大升级,完全遵循 PSR-15(HTTP Server Request Handlers)标准。与 Slim 3 中 function(Request $request, Response $response, callable $next) 的三参数模式不同,Slim 4 中间件必须接收 Request 和 RequestHandler 实例,并始终返回 ResponseInterface 实例——不再允许直接调用 $next(),而是通过 $handler->handle($request) 获取下游响应。
以下是原始 Slim 3 中间件的 Slim 4 等效实现:
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Exception\HttpNotFoundException;
$app->add(function (Request $request, RequestHandler $handler): Response {
$publicRoutes = ['ping', 'guest', 'login', 'api-login', 'logout'];
// 获取当前路由信息(需确保已启用路由解析中间件)
$route = $request->getAttribute('route');
if (!$route) {
throw new HttpNotFoundException($request);
}
$routeName = $route->getName();
// 非公开路由需校验 Token
if (!in_array($routeName, $publicRoutes, true)) {
$tokenStatus = checkTokenStatus(); // 保持原有逻辑,但建议注入依赖而非全局函数
if (!$tokenStatus) {
// 构造重定向响应(注意:Slim 4 的 withRedirect 是 Response 方法)
return $handler->handle($request)
->withStatus(302)
->withHeader('Location', '/login');
// ✅ 正确做法:若需立即跳转且不执行后续中间件/路由,应直接返回新 Response
// return $response->withRedirect('/login'); // ❌ 错误:$response 未定义
}
}
// 继续请求处理链
return $handler->handle($request);
});⚠️ 关键注意事项:
- $handler->handle($request) 必须被调用且返回 ResponseInterface:它代表整个中间件栈和路由处理器的最终响应,不可省略。
- 重定向不能复用旧 $response 变量:Slim 4 中 Response 是不可变对象,withRedirect() 返回新实例,且中间件不接收 $response 参数,因此需显式构造或委托 $handler 后修改。
- 路由属性可用性前提:$request->getAttribute('route') 仅在 RoutingMiddleware 已注册并执行后才有效(Slim 4 默认已启用),否则会返回 null。
- 异常处理更规范:推荐使用 Slim\Exception\HttpNotFoundException(继承自 PSR-7 兼容异常),框架会自动将其转为 404 响应。
- 函数式中间件 vs 类中间件:生产环境建议将逻辑封装为类(实现 MiddlewareInterface),便于测试与依赖注入;checkTokenStatus() 应重构为可注入的服务,避免全局函数耦合。
总结:Slim 4 中间件迁移核心在于理解「请求处理器链」模型——每个中间件是链条中的一环,通过 $handler->handle($request) 将控制权交予下游,并对返回的响应进行增强或拦截。坚持“输入 Request,输出 Response”的单一职责原则,即可写出清晰、可组合、符合标准的现代中间件。


















