Hyperf路由前缀配置核心是@Controller(prefix: "...")注解或Router::group(),前者作用于类内所有方法并支持版本隔离,后者用于跨控制器统一前缀;二者均仅作静态字符串拼接,不处理逻辑,且不可混用。

Hyperf 的路由前缀配置,核心就两条路:用 @Controller(prefix: "...") 注解,或在 config/routes.php 里用 Router::group()。前者管类内所有方法,后者管一组路由定义,别混用或漏掉斜杠。
Controller 类上用 prefix 参数最常用
这是绝大多数 API 控制器的首选方式,它让路径结构清晰、复用率高,且天然支持版本隔离。
-
@Controller(prefix: "/api/v2")必须写成字符串字面量,不支持变量或表达式 - 方法级注解的
path是相对路径,#[GetMapping(path: "users")]拼出来就是GET /api/v2/users;如果误写成path: "/users",多数情况下 Hyperf 会 normalize 成单斜杠,但风格不统一容易引发协作困惑 - prefix 不做任何逻辑判断,只是字符串拼接 —— 它不会自动加/、去重/、处理尾部斜杠,所以
prefix: "/api/"和prefix: "/api"在语义上等价,但建议统一去掉末尾斜杠,避免和方法 path 中的开头斜杠冲突 - 如果类里混用了
@AutoController和@Controller,只有@Controller生效;@AutoController会忽略 prefix
routes.php 里用 group 做跨控制器前缀
适合需要把多个不同命名空间的控制器(比如 App\Controller\V1\* 和 App\Controller\V2\*)挂到同一前缀下,或者想给非注解路由(如闭包路由)加前缀。
-
Router::group(['prefix' => '/admin'], function () { ... });中的prefix是数组键,不是函数参数,别写成Router::group('/admin', ...)—— 那会报错ArgumentCountError - group 内部定义的路由,其路径自动前置
/admin,例如get('dashboard', ...)最终注册为GET /admin/dashboard - group 支持嵌套,但嵌套过深会让路由表难以调试;建议单层 group + 明确的控制器命名空间划分
- 中间件、命名空间等选项可一并传入 group 数组,比如
['prefix' => '/api', 'middleware' => [AuthMiddleware::class]]
前缀冲突和常见错误现象
实际开发中最容易栽跟头的地方,往往不是不会配,而是没意识到前缀是“静态拼接”这个本质。
- 启动时报错
Route not found for GET /api/users,但代码里明明写了@Controller(prefix: "/api")和#[GetMapping(path: "users")]—— 八成是注解没被扫描到,检查是否漏了use Hyperf\HttpServer\Annotation\Controller;,或类没放在scan配置的目录里 - 请求返回 405 Method Not Allowed,路径对但方法错 —— 可能是
@Controller类里写了#[PostMapping],但前端发的是 GET,这种错误和 prefix 无关,但新手常误以为是前缀导致的路由错位 - API 版本升级后旧路由还能访问 —— 如果只改了
@Controller(prefix: "/api/v2"),但忘了删掉 v1 的 controller 类或 routes.php 里的 v1 group,就会出现双版本共存却未显式拒绝的情况,违反版本管理原则 - 使用
Router::addRoute()手动注册时,它不走 prefix 机制,完全独立;若同时存在注解路由和手动路由,需自行保证前缀一致性
复杂点在于 prefix 和中间件、版本策略的耦合
单独配前缀很简单,难的是它一旦和权限、版本、日志等中间件绑在一起,就容易变成“改一处、漏十处”。比如你在 @Controller(prefix: "/api/v2", middleware: [RateLimitMiddleware::class]) 里加了限流,但 v1 路由还在 routes.php 里用 group 定义且没配限流,线上行为就不一致。更隐蔽的是,Hyperf 的路由分发树在启动时固化,prefix 修改后必须重启服务才能生效 —— 这点在热更新或容器滚动发布时特别容易被忽略。











