Hyperf DI容器不识别未扫描类,主因是scan.paths漏路径、未执行composer dump-autoload -o及di:init-proxy,且类须含有效注解(如#[Service])才注册。

Hyperf 的 DI 容器根本不会“看到”没被扫描到的类——不是注入失败,是连注册这一步都没发生。必须先让类进容器,后续注入、路由、事件等才可能生效。
scan.paths 漏了自定义目录,类压根不被读取
Hyperf 默认只扫描 BASE_PATH . '/app',如果你把服务放在 /Domain、/Infrastructure 或 /Modules 下,不显式加路径,Finder 就不会打开那些文件,更别说解析注解。
- 检查
config/autoload/annotations.php中的scan.paths,确认已包含所有实际目录,例如:[BASE_PATH . '/app', BASE_PATH . '/Domain', BASE_PATH . '/Infrastructure'] - 路径必须用正斜杠、绝对路径;
app/Domain或.\Domain这类写法无效 - 改完后必须运行
composer dump-autoload -o,否则 PHP 自动加载器根本找不到这些类,注解自然无从谈起 - Windows 用户特别注意:路径中不能含反斜杠,
BASE_PATH . '\Domain'会导致扫描静默跳过
类存在但没被注解标记,容器直接忽略
即使文件在扫描路径里,Hyperf 也只处理带有效注解(如 #[Service]、#[Controller]、#[Listener])的类。没有注解,就不会注册进容器,@Inject 再多也没用。
- 确认类顶部有至少一个框架识别的注解,比如
#[Service](非@Service注释) - PHP 8+ 属性类型提示
public UserService $userService;不算注解,也不会触发注册 - 自定义注解类必须自己实现为
#[Attribute],且作用域匹配(如#[Attribute(Attribute::TARGET_CLASS)]),否则反射读不到 - 可临时调用
ReflectionManager::getAllClasses()查看实际扫描到的类数量,对比预期值快速定位遗漏
Finder 扫描过程静默失败,文件被跳过
Symfony\Finder 在某些条件下会跳过文件,且不报错——你改了代码,却看不到效果,大概率是文件根本没进扫描流水线。
- 文件名含空格或非法字符(如
User Service.php)会被 Finder 忽略 - 符号链接默认不跟随,若目录是软链,需在
annotations.php中启用follow_links => true - PHP 语法错误(少括号、错用
??等)会导致 Ast 解析失败,当前文件直接continue,不收集也不报错 - 嵌套过深(如
/app/Domain/Order/V1/Dto/Request/CreateOrderRequest.php)可能触发 Finder 默认限制,建议控制层级在 4 层以内
SCAN_CACHEABLE=true 但缓存文件缺失或过期
SCAN_CACHEABLE 不是自动缓存开关,它只是个条件判断:只有当 runtime/container/annotation/ 下存在合法的缓存 PHP 文件时,才会跳过扫描。首次部署或路径变更后,缓存文件往往不存在。
- 必须手动执行
php bin/hyperf.php di:init-proxy生成注解元数据和代理类 - Docker 构建时确保
runtime/container/没被.dockerignore过滤,且ENTRYPOINT不会清空它 - 加密发布前,必须保留已生成的
runtime/container/annotation/目录及其所有.php文件 - 修改注解后,仅清
runtime/不够,必须重跑di:init-proxy,否则仍用旧缓存
最常被忽略的是:改了 scan.paths 却忘了 composer dump-autoload -o,或者跑了 di:init-proxy 却没确认 runtime/container/annotation/ 下真有对应类的缓存文件——这两步缺一不可,且顺序不能颠倒。


















