Slim Framework 4中间件获取所有路由返回500错误问题
问题根因
接口返回500由三类问题共同导致:
- 中间件不符合Slim执行规范:
__invoke方法必须返回Psr\Http\Message\ResponseInterface实例,你的代码执行print_r后直接终止,没有返回响应对象,框架会直接抛出类型错误。 - 冗余容器配置:Slim框架启动时已经自动完成
RouteCollectorInterface的实例绑定,你自定义的绑定闭包如果在App实例初始化完成前执行,会拿到未注册路由的空收集器实例。 - 中间件挂载顺序错误:Slim中间件是外层先执行、内层后执行的栈结构,如果你的ACLMiddleware挂载在框架自带的
RoutingMiddleware外层,执行到你的逻辑时路由还未完成解析,无法拿到有效路由数据。
修复步骤
1. 修正中间件代码
优先从请求上下文获取路由收集器,不需要手动依赖注入,最后必须返回处理后的响应对象:
namespace App\Application\Middleware; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\RequestHandlerInterface as RequestHandler; use Slim\Psr7\Response; use Slim\Routing\RouteContext; final class ACLMiddleware { public function __invoke(Request $request, RequestHandler $handler): Response { // 从请求中获取路由上下文,路由解析完成后才能正常读取 $routeContext = RouteContext::fromRequest($request); $routeCollector = $routeContext->getRouteCollector(); // 获取所有已注册路由 $routes = $routeCollector->getRoutes(); // 调试输出建议加exit终止,或写入日志避免破坏响应结构 print_r($routes); exit; // 正式逻辑请删除调试代码,正常执行后续中间件并返回响应 // $response = $handler->handle($request); // return $response; } }
2. 清理冗余配置
删除容器配置中自定义的RouteCollectorInterface::class绑定闭包,框架默认绑定的实例可以直接使用,不需要手动覆盖。
3. 调整中间件挂载顺序
保证ACLMiddleware挂载在RoutingMiddleware内层(即比RoutingMiddleware晚添加),确保执行ACL逻辑时路由已经完成解析:
<?php // 先添加路由中间件,会在栈内层先执行完成路由解析 $app->add(\Slim\Middleware\RoutingMiddleware::class); // 后添加ACL中间件,在栈外层执行时路由已经解析完毕 $app->add(\App\Application\Middleware\ACLMiddleware::class); // 错误中间件可以放在最外层 $app->addErrorMiddleware(true, true, true);
补充说明:如果需要获取当前请求匹配到的单条路由,直接调用
$routeContext->getRoute()即可,不需要遍历全量路由列表。
内容的提问来源于stack exchange,提问作者Laercio Silva
相关产品推荐
相关产品推荐

