
本文详解如何将 Slim 3 的闭包式中间件升级为 Slim 4 兼容的 PSR-15 标准中间件,重点解决 callable $next 替换为 RequestHandler、响应返回机制变更及路由校验逻辑适配等核心问题。
本文详解如何将 slim 3 的闭包式中间件升级为 slim 4 兼容的 psr-15 标准中间件,重点解决 `callable $next` 替换为 `requesthandler`、响应返回机制变更及路由校验逻辑适配等核心问题。
Slim 4 严格遵循 PSR-15 中间件规范,彻底摒弃了 Slim 3 中 function(Request, Response, callable $next) 的三参数签名,转而采用 function(Request, RequestHandler): ResponseInterface 的标准形式。这意味着你不再调用 $next($request, $response),而是通过 $handler->handle($request) 获取响应,并必须显式返回该响应对象。
以下是原 Slim 3 中间件的完整 Slim 4 迁移版本:
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Exception\HttpNotFoundException;
// 注册中间件(推荐:在依赖注入容器中定义或直接添加)
$app->add(function (Request $request, RequestHandler $handler): Response {
$publicRoutes = [
'ping',
'guest',
'login',
'api-login',
'logout'
];
// 获取当前路由对象(注意:需确保路由解析已执行)
$route = $request->getAttribute('route');
// 路由不存在时抛出标准异常(Slim 4 自动处理为 404)
if (!$route) {
throw new HttpNotFoundException($request);
}
$routeName = $route->getName();
// 非公开路由需校验 Token
if (!in_array($routeName, $publicRoutes, true)) {
$tokenStatus = checkTokenStatus(); // 保持原有逻辑不变
if (!$tokenStatus) {
// 构建重定向响应(注意:返回 Response,而非调用 $next)
return $request->getUri()->withPath('/login')
->withScheme($request->getUri()->getScheme())
->withHost($request->getUri()->getHost())
->withPort($request->getUri()->getPort())
->withUserInfo($request->getUri()->getUserInfo())
? $request->getAttribute('response')->withStatus(302)->withHeader('Location', '/login')
: $request->getAttribute('response')->withStatus(302)->withHeader('Location', '/login');
// ✅ 更简洁写法(推荐):
// return $request->getAttribute('response')->withStatus(302)->withHeader('Location', '/login');
}
}
// ✅ 关键变更:调用 handler 并返回其响应
return $handler->handle($request);
});⚠️ 重要注意事项:
- $request->getAttribute('response') 是安全的:Slim 4 在请求生命周期中自动注入默认 Response 实例,可通过 $request->getAttribute('response') 获取(无需手动传入);
- 不要自行创建 Response 实例:除非特殊需求,优先复用 $request->getAttribute('response');
- checkTokenStatus() 函数需保持兼容:确保该函数不依赖 Slim 3 特有上下文(如旧版 Response 或 App 实例);
- 路由属性前提:$request->getAttribute('route') 仅在路由已匹配且 RoutingMiddleware 已执行后才存在——请确认该中间件注册顺序在 RoutingMiddleware 之后(通常 add() 默认满足);
- 异常处理更规范:使用 HttpNotFoundException 替代自定义 NotFoundException,确保与 Slim 4 错误处理器无缝集成。
总结而言,Slim 4 中间件迁移的核心是:参数签名标准化、$handler->handle($request) 替代 $next()、强制返回 ResponseInterface 实例、复用请求附带的响应对象。遵循此模式,即可平滑升级所有中间件,同时提升代码可测试性与框架兼容性。

















