$bind 存绑定规则(类名、闭包等),不实例化;$instances 存已创建的单例对象,直接复用。bind传对象会自动移入instances,清空bind对应项。

bind 和 instances 都是容器的属性,但用途完全不同
简单说:$bind 存的是「怎么造」,$instances 存的是「已经造好的」。两者不重叠、不替代,框架内部严格按角色分工使用。
bind 属性只存绑定规则,不存实例
$bind 是一个映射数组,键是抽象标识(比如 'think\Request' 或自定义的 'cache'),值是具体实现——可能是类名字符串、闭包、接口实现类,甚至 null(表示延迟解析)。它本身不触发任何实例化。
- 写
$app->bind('UserRepo', 'app\repository\UserRepository'),只是记下“要 UserRepo 就去 new 这个类” - 写
$app->bind('logger', function() { return new FileLogger(); }),只是记下“要 logger 就调这个闭包” - 如果值是对象(比如
$app->bind('stdclass', new \stdClass())),框架会自动把它挪进$instances,$bind里只留键名,值被清空 - 调用
getAlias('think\Request')实际就是查$bind['think\Request']的值;没命中就原样返回键名
instances 属性只存已创建的单例对象
$instances 是真正的对象缓存池,所有通过 make() 或 get() 首次获取后被标记为单例(比如用 singleton() 绑定的)的对象,都会落在这里。后续再 make() 同一个抽象,直接从这里取,跳过构造逻辑。
-
$app->instance('db', $pdo)会直接把$pdo塞进$instances['db'],不经过$bind -
bindRequest()内部先make(Request::class),初始化完立刻存进$instances[Request::class] - 手动调
$app->make('think\Request')两次,第二次不会重新解析$_SERVER,因为直接从$instances返回了 - 注意:
$instances键名是标准化后的(经getAlias()处理),所以$app->bind('req', 'think\Request')后再$app->get('req'),最终还是从$instances['think\Request']取
容易混淆的坑:bind 传对象时会被自动“搬家”
这是最常踩的点:你以为 bind('cache', $obj) 是把对象记在 $bind 里,其实框架检测到第二个参数是对象,会立刻执行 instance('cache', $obj),把对象塞进 $instances,同时清空 $bind['cache']。所以之后调 getAlias('cache') 返回 'cache'(没绑定值),但 get('cache') 仍能拿到对象——因为它走的是 $instances 分支。
真正需要复用已有对象时,直接用 instance() 更明确;想控制构造逻辑(比如每次 new 新实例),就用 bind() + 类名/闭包,别传对象。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











