hyperf 3.1 注解扫描失效主因是 scan.paths 未显式配置子目录、代理缓存未重建、注解类未适配 php 8.1+ attribute 语法及缓存开关设置不当;需明确列出控制器路径、清空 runtime/container/annotation/ 并执行 di:init-proxy、确保注解类带正确 attribute 声明且 cacheable 设为 false。

Hyperf 3.0 升级到 3.1 后注解扫描失效、控制器找不到,核心问题不是代码写错了,而是升级后几处关键配置和缓存机制发生了变化——尤其是注解扫描路径、代理类重建逻辑和缓存开关行为。
检查 annotations.php 中的 scan.paths 是否显式包含控制器目录
Hyperf 3.1 默认不再递归扫描子目录。即使你写了 'paths' => ['app'],app/Controller 或 app/Http/Controller 下的类也不会被识别。
- 必须明确列出具体路径,例如:
['app/Controller', 'app/Http/Controller'] - 路径用正斜杠,不要用 Windows 风格反斜杠(
app\Http\Controller会失效) - 若控制器在自定义命名空间下(如
MyApp\Controller),对应路径也得加进去,比如BASE_PATH . '/app/MyApp'
强制重建注解代理类和容器缓存
升级后 runtime/container/annotation/ 下的旧缓存可能与 3.1 的扫描器不兼容,导致注解元数据为空或缺失。
- 先清空:
rm -rf runtime/container/annotation/ - 再执行:
php bin/hyperf.php di:init-proxy - 如果用了自定义注解,还需运行:
php bin/hyperf.php annotation:scan - Docker 环境注意:确保
.dockerignore没过滤runtime/,且构建后未自动清空
确认注解类已适配 PHP 8.1+ Attribute 语法
Hyperf 3.1 完全依赖 PHP 原生 Attribute,任何残留的 Doctrine 风格注解(@Controller)或未声明作用域的 #[Attribute] 都会导致扫描跳过整个类。
- 控制器上的
#[Controller]、#[GetMapping]必须来自官方包,且其定义类已带#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] - 自定义注解类不能继承
AbstractAnnotation(该类在 3.1 中已移除) - 每个注解类顶部必须有
use Attribute;,构造函数参数必须带类型声明(如public string $prefix = '')
关闭注解缓存并验证是否生效
开发阶段若开启注解缓存('cacheable' => true),改了注解或路径后不重建缓存,服务就永远“看不见”新控制器。
- 检查
config/autoload/annotations.php中是否设为'cacheable' => false - 临时加一句日志验证扫描是否触发:
var_dump('scanning: ', $className);放在ReflectionManager::reflectClass()内部(仅调试用) - 启动时加
--debug参数:php bin/hyperf.php start --debug,观察控制台是否输出扫描到的控制器类名











