$container->get()用于从hyperf容器中获取已注册服务的实例,若未实例化则自动解析依赖并创建(单例模式),否则返回缓存实例;需确保类已通过注解、配置或手动绑定注册,否则抛出“entry not found”错误。

Hyperf 容器 get 方法的基本用法
get 是 Hyperf 依赖注入容器的核心方法,用于从容器中获取已注册的类、接口或别名对应的实例。它不是“创建新对象”,而是触发容器的解析逻辑——如果该服务未实例化,容器会按定义自动实例化并返回;如果已存在(且是单例),则直接返回缓存实例。
最常见写法:
$user = $container->get(UserService::class);注意:传入的是类名(
string 或 class-string),不是字符串类名如 'UserService'(除非你显式绑定过该字符串)。
- 必须确保目标类已在容器中注册(通过注解
@Inject、配置文件dependencies.php、或手动set绑定) - 若类有构造参数,容器会自动递归解析依赖,无需手动传参
- 不支持传入构造参数给
get(这点和 Laravel 的makeWith不同)
为什么调用 get 会报 “Entry XXX is not found in container”?
这是最常遇到的错误,本质是容器找不到对应服务定义。不是类不存在,而是没“告诉容器怎么造它”。常见原因:
- 类没加
@Inject注解,也没在dependencies.php中手动绑定 - 用了接口绑定,但
get时传的是实现类而非接口(例如绑了UserInterface::class => UserService::class,却调get(UserService::class)) - 类在非扫描路径下(比如放在
app/Utils但scan配置没覆盖该目录),导致注解未生效 - 使用了
make或get时传错大小写或命名空间(PHP 类名区分大小写)
调试建议:用 $container->has(UserService::class) 先判断是否存在;或查看 var_dump($container->getBindings()) 确认绑定关系。
get 和 make 的关键区别在哪?
两者都返回实例,但行为不同:get 默认走单例模式(Singleton),make 每次都新建实例(Prototype)。这直接影响对象生命周期和状态共享。
- 若类已通过
set显式设为单例($container->set(..., $obj)或$container->singleton(...)),get总返回同一实例;make仍会新建 - 若类仅靠注解自动注册(无显式
singleton调用),Hyperf 默认按单例处理,所以get和make表现一致 —— 但这属于默认行为,不是规范保证 - 生产环境慎用
make获取有状态的服务(如带属性缓存的 Repository),容易引发意外交互
简单记:需要复用、无副作用、希望节省资源 → 用 get;需要隔离状态、测试模拟、或明确要新实例 → 用 make。
在非容器上下文里怎么安全调用 get?
Hyperf 的 $container 实例不能全局裸用,尤其在协程切换后可能丢失上下文。直接写 Container::get()->get(...) 在命令行或定时任务中看似能跑,但实际可能拿到错误的容器实例(比如主进程容器而非当前协程容器)。
- 推荐方式:通过
ApplicationContext::getContainer()获取当前上下文容器 - 在 Command 类中,优先用
$this->getApplication()->getContainer() - 绝对避免在静态方法、全局函数或协程外长期持有容器引用
- 若在
onWorkerStart回调中提前保存容器,后续协程中调用get可能失效 —— 必须每次按需取当前上下文容器
Hyperf 的容器是协程安全的,但“安全”前提是每次都从正确上下文拿实例,而不是复用一个旧引用。











