hyperf 的 make 函数本质是容器解析而非 new 实例,通过 containerinterface 递归解析构造函数依赖并自动注入,仅支持类名或接口名一个参数;若含不可解析原始类型参数(如 string $apihost),须改用 makewith 显式传参。

Hyperf 的 make 函数本质是容器解析,不是 new 实例
Hyperf 的 make 不是简单封装 new,而是通过依赖注入容器(ContainerInterface)完成对象实例化和依赖自动注入。它会读取类的构造函数参数类型提示,递归解析依赖,最终返回完全初始化的对象。
常见错误:直接传入参数数组期望像 Laravel 的 make 那样覆盖构造参数 —— Hyperf 的 make 默认不支持运行时传参(除非显式绑定或使用 makeWith)。
-
make只接受一个参数:string|class-string,即类名或接口名 - 若类未在容器中显式绑定,且无构造参数或参数类型可被容器解析,则自动实例化
- 若构造函数含不可解析类型(如
string $name、int $timeout),会抛出EntryNotFoundException
什么时候必须用 makeWith 而不是 make
当目标类构造函数含「无法由容器自动推断的原始类型参数」时,make 会失败,必须改用 makeWith 显式传参。
例如:
class UserService
{
public function __construct(private string $apiHost, private int $timeout) {}
}
此时调用 $container->make(UserService::class) 会报错:Entry [string] not found。
- 正确做法:
$container->makeWith(UserService::class, ['apiHost' => 'https://api.example.com', 'timeout' => 5000]) - 键名必须与构造函数参数名严格一致(PHP 8.0+ 支持命名参数,但 Hyperf 容器仍依赖字符串键匹配)
-
makeWith是make的补充,不是替代;高频使用说明设计上可能过度依赖运行时配置,建议优先通过配置中心或接口绑定解耦
在非容器上下文(如命令行、单元测试)中调用 make 的前提
Hyperf 的 make 必须在容器已启动、依赖已注册后才能使用。直接在 bin/hyperf.php 顶层或未启动框架时调用会报 Call to a member function make() on null。
- 确保已执行
BaseApplication::getContainer()或从ApplicationContext获取容器:ApplicationContext::getContainer()->make(...) - 在
Command类中,应放在handle()方法内,而非__construct()—— 此时容器可能尚未就绪 - 单元测试中需用
Mockery::mock(ContainerInterface::class)或启动最小化容器(如ContainerFactory::createContainer())
make 和 get 的关键区别:单例 vs 每次新建
make 每次都返回新实例(prototype 行为),而 get 在容器中已存在实例时返回缓存对象(singleton 行为)—— 但前提是该类已被绑定为单例。
- 未显式绑定时:
make(A::class)和get(A::class)效果相同(都新建) - 显式绑定单例后:
Container::setSingleton(A::class, fn() => new A()),再调用get(A::class)才复用,make仍新建 - 别误以为
get总是单例 —— 它只是“尝试获取已有”,没绑定就 fallback 到新建,行为不如make确定
真正控制生命周期靠绑定方式(setSingleton / setInstance / setAlias),而不是选 make 还是 get。











