新项目无脑用注解路由,老项目迁移或需集中管控时才考虑配置文件路由;config/routes.php用于全局中间件、动态路由生成、统一审计及正则约束,注解路由需开启扫描、控制器标注、重启服务且避免AutoController与Controller混用。

直接说结论:新项目无脑用注解路由,老项目迁移或需集中管控时才考虑配置文件路由。
什么时候必须用 config/routes.php
配置文件路由不是“过时”,而是承担特定职责:
- 全局中间件注册(比如跨域、日志、限流)必须在
Router::group中声明,注解无法覆盖整个应用入口层 - 需要动态生成路由时(例如从数据库读取后台菜单并注册为路由),
routes.php是唯一可执行逻辑的地方 - 团队有强约定:所有 API 版本号、灰度路径、AB 测试路由必须统一收口审计,这时硬编码在 PHP 文件里比分散在几十个控制器里更可控
-
Router::addRoute支持正则约束写法如'/user/{id:\d+}',而注解里的path参数不支持内联正则(只能靠参数注解@Param配合验证器)
注解路由真正生效的 3 个硬性条件
很多人写了 #[GetMapping] 却收不到请求,不是语法错,是漏了底层开关:
当代理已经知道网站路由或内容URL,并且在启动前需要有效的sitemap XML、sitemap索引或robots.txt引用时,请使用sitemap。这是一个发布构件技能,而不是爬虫或SEO平台。
- 确认
config/autoload/annotations.php中'scan' => true已开启,且'paths'包含控制器目录(如app/Controller) - 控制器类必须带
#[Controller]或#[AutoController]—— 单独写#[GetMapping]在非控制器类上会被忽略 - 运行过
php bin/hyperf.php gen:route或重启服务(Swoole 常驻进程,改注解后不重启=没生效)
#[Controller(prefix: "...")] 和 #[AutoController] 别混用
这是最常踩的命名冲突坑:
-
#[AutoController]会自动把方法名转成路径,比如index()→GET /test/index;它**不接受**prefix参数,加了也无效 -
#[Controller(prefix: "/api/v2")]必须配合方法级注解(如#[GetMapping(path: "users")]),最终路径是拼接结果:/api/v2/users - 如果同时给一个类加了两个注解,Hyperf 会优先按
#[Controller]处理,#[AutoController]被静默丢弃 - 路径拼接是纯字符串连接,
prefix: "/api/"+path: "users"=/api//users(双斜杠)。务必保证 prefix 不以/结尾,或 path 以/开头,二者选一
注解路由的“高内聚”优势只在代码组织层面成立;真要查某条路由到底注册成了什么,别翻控制器,直接跑 php bin/hyperf.php route:list —— 它输出的是最终生效的路由表,和你写的注解可能差一个 prefix 拼接或中间件注入。


















