Hyperf注解扫描失败主因有三:scan.paths路径错误或不可读、ignore_annotations误删关键注解、缓存未清除;需确认路径真实存在、ignore_annotations为空、执行di:clear与di:dump。

scan.paths 配置路径是否真实存在且可读
Hyperf 的注解扫描器不会报错提示“目录不存在”,而是静默跳过。如果 config/autoload/annotations.php 中的 scan.paths 写成 ['app/Controllers'](多了一个 s),而实际目录是 app/Controller,整个控制器层就完全不会被扫描。
检查方式很简单:在终端执行 ls -l app/Controller,确认目录名拼写、大小写、是否存在;Windows 用户还需注意路径分隔符是否被误写为反斜杠 \(PHP 会当作转义处理)。
- 用
BASE_PATH . '/app/Controller'替代相对路径,避免工作目录变动影响 - 路径中不要包含
../或变量插值(如$env . '/app'),扫描器不解析 PHP 表达式 - 若用 Docker,确认宿主机映射路径与容器内路径一致,
ls -l在容器内运行才有效
ignore_annotations 列表是否误删了关键注解
默认 ignore_annotations 是空数组,但一旦手动配置,就必须显式保留所有需要生效的注解类名。常见错误是只写了 ['AutoController'],却漏掉 'GetMapping'、'PostMapping' 等方法级注解,导致路由注解被跳过,类被注册但方法无路由。
Hyperf 路由依赖两类注解协同:类上必须有 #[Controller] 或 #[AutoController],方法上必须有 #[GetMapping] 等动词注解。任一环节被 ignore_annotations 拦截,整条链就断了。
- 检查
config/autoload/annotations.php中scan.ignore_annotations值是否为[](开发环境建议始终为空) - 若确需忽略某些自定义注解,请只列具体类名,如
['MyCustomAnnotation'],不要写模糊匹配 - 执行
php bin/hyperf.php route:list,输出为空或缺少目标路由,基本可锁定是注解被过滤
扫描结果未刷新导致旧缓存干扰
Hyperf 注解扫描结果会生成缓存文件(runtime/container/annotations.php),修改 scan.paths 或增删注解后不清理,容器仍按旧定义工作——比如你刚把 app/Controller 加进路径,但缓存里还是只扫 app/Http,自然找不到新控制器。
这不是 bug,是设计使然:缓存提升启动速度,但也要求开发者主动管理生命周期。
- 每次修改
scan.paths或ignore_annotations后,必须执行php bin/hyperf.php di:clear - 再运行
php bin/hyperf.php di:dump,强制重扫并重建 DI 映射 - 顺手清掉
runtime/cache和runtime/container目录更保险,尤其在 CI/CD 部署时
Phar 模式下 scan.paths 必须用绝对路径
Phar 打包后,__DIR__ 指向 phar 包内部路径,相对路径如 'app/Controller' 会解析失败。Hyperf 在 Phar 模式下无法自动 resolve PSR-4 路径,必须显式提供完整物理路径。
这和普通开发模式完全不同:本地跑得好,打包后 404,大概率卡在这里。
- 在
config/autoload/annotations.php中改写为:BASE_PATH . '/app/Controller' -
BASE_PATH是 Hyperf 内置常量,在 Phar 和非 Phar 下都指向项目根目录,跨平台安全 - 别用
dirname(__FILE__)或realpath(),它们在 Phar 中行为不可靠
ignore_annotations 一旦非空,就必须把所有要用的注解名列全,漏一个,路由就少一条;缓存不清,改了等于没改。**


















