中间件顺序不生效主因是server名未配对,需确保middlewares.php中键名与server.php里servers数组的name值完全一致;其次须用优先级数值(非数组顺序)控制执行先后,routermiddleware必须前置,且注解扫描配置需正确。

中间件顺序不生效,大概率是没配对 server 名
Hyperf 的 middlewares.php 配置不是全局生效的,它按 server 名分组。如果你在 config/autoload/middlewares.php 里写了 'http' => [...],但 config/autoload/server.php 里实际定义的 HTTP Server 名叫 'api' 或 'web',那这组中间件根本不会加载。
检查方式很简单:打开 config/autoload/server.php,找到 'servers' 数组,确认每个 'name' 值;再对照 middlewares.php 的键名是否完全一致(大小写敏感、不能多空格)。
-
'http'是默认名,仅当server.php中存在'name' => 'http'时才匹配 - 自定义 server 名如
'admin',就必须在middlewares.php中显式声明'admin' => [...] - 配置键名不匹配时,Hyperf 不报错,只是静默跳过——这是最常被忽略的「无感失败」
数组索引顺序 ≠ 执行顺序,优先级数值才是关键
Hyperf 2.x(尤其 2.2+)对中间件执行顺序的控制逻辑已从「数组顺序」转向「优先级数值」。即使你在 'http' => [] 里把 AuthMiddleware 放第一位,只要它没显式指定优先级,就可能被其他带 => 10 的中间件插队。
正确写法必须带权重映射:
'http' => [
\App\Middleware\AuthMiddleware::class => 10,
\App\Middleware\PermissionMiddleware::class => 8,
\App\Middleware\LoggingMiddleware::class => 3,
],
- 数值越大越早执行(请求阶段),
0或不指定则默认最后 - 同优先级时才按数组顺序 fallback,但别依赖它
- 注解方式(
#[Middleware(AuthMiddleware::class, 10)])和路由级->middleware([...])同样遵循该规则
RouterMiddleware 必须在所有业务中间件之前
如果 GET /api/user 直接返回 404,且日志中 $request->getAttribute('route') 为 null,说明请求压根没进路由系统——RouterMiddleware 被挡在了后面。
这个中间件不是可选组件,它是路由解析的唯一入口,必须排在所有依赖 route 属性的中间件之前,比如鉴权、权限、日志(需记录路由信息)等。
- 错误示例:
AuthMiddleware在RouterMiddleware前 →$request->getAttribute('route')拿不到值,AuthMiddleware可能直接 throw 异常或返回 401 - 正确姿势:把
\Hyperf\HttpServer\Middleware\RouterMiddleware::class => 999显式放在middlewares.php最前面 - 注意:不要用
new RouterMiddleware()实例化,必须用类名字符串 + 优先级
扫描配置失效会导致注解中间件完全不注册
即使 middlewares.php 写对了,若 config/autoload/scan.php 的路径或忽略项出错,@AutoController、@GetMapping、@Middleware 这些注解根本不会被扫描到,整个路由和中间件注册链就断了。
重点检查两处:
-
'paths'是否包含控制器真实目录,比如写成['app/Controllers'](多了一个 s)而实际是app/Controller -
'ignore_annotations'是否误删了'Middleware'或'AutoController'—— 默认值为空数组,改过就得手动补全 - 验证方法:运行
php bin/hyperf.php route:list --format=json,目标路由不在输出里,基本就是扫描问题
中间件顺序问题最难 debug 的地方在于:它不报错、不抛异常,只默默跳过或错位执行。优先级数值、server 名匹配、RouterMiddleware 位置、注解扫描,四个点只要漏一个,行为就不可控。











