Hyperf 多实现需用接口名@name注册别名,如App\Contract\UserServiceInterface@aliyun→App\Service\AliyunUserService::class;注入时@Inject(name:'aliyun')或make(UserServiceInterface::class,['name'=>'qcloud'])指定;makeAll()获取所有命名实现。

Hyperf 默认不支持接口有多个实现类时直接类型提示注入,会抛 ContainerException: Cannot resolve type "App\Contract\UserServiceInterface"。必须显式告诉容器“用哪一个”。
在 dependencies.php 里注册命名绑定
这是最常用也最可控的方式。关键不是只写接口 → 实现映射,而是用 接口名@name 格式注册别名:
-
App\Contract\UserServiceInterface@aliyun→App\Service\AliyunUserService::class -
App\Contract\UserServiceInterface@qcloud→App\Service\QcloudUserService::class - 主键
App\Contract\UserServiceInterface可以不设,或设为默认实现(但不推荐)
注意:key 必须带 @name 后缀,否则 make() 的 name 参数无法匹配;值必须是带命名空间的完整类名,且文件路径要符合 PSR-4。
@Inject(name: 'xxx') 显式指定实现
控制器或服务中用注解注入时,@Inject 必须带 name 属性,否则仍会报错:
#[Inject(name: 'aliyun')] private UserServiceInterface $userService;
常见错误:
- 漏写
name,或写成#[Inject('aliyun')](无效) - 变量类型提示没写全限定名,比如写
private UserServiceInterface $userService(PHP 解析为当前命名空间下类) - 大小写不一致:
@aliyun注册了,却传name: 'Aliyun'
运行时用 make() 指定 name 参数
需要动态选实现时,用 $container->make() 更灵活:
$svc = $this->container->make(UserServiceInterface::class, ['name' => 'qcloud']);
失败常见原因:
- 没在
dependencies.php中注册对应接口名@name的映射 - 实现类构造函数依赖未绑定(如缺
LoggerInterface),导致实例化失败,掩盖了“找不到实现”的原始问题 - 传入的
name值含空格或大小写错误,比如' notify '或'Notify'
批量获取所有实现用 makeAll()
如果业务需要遍历全部实现(比如广播通知、策略聚合),用 makeAll():
$allServices = $this->container->makeAll(UserServiceInterface::class);
它会返回一个数组,包含所有已注册的命名实现(即所有 接口名@xxx 对应的实例)。注意:makeAll() 不会返回未命名绑定的主键实现,只认 @name 形式注册的条目。
最容易被忽略的是:命名绑定必须严格匹配大小写和空格,且 make() 和 @Inject(name:) 依赖的是同一套注册机制——少配一个 @name,就少一个可选实现。


















