Db类是静态门面,无需手动加载或new实例,仅需use think\Db即可使用;db()助手函数每次新建实例,事务和连接不复用,性能敏感场景应优先使用Db::name()。

Db 类不是“加载”出来的,而是直接可用的静态门面类。ThinkPHP 5/6/8 中没有「手动加载查询构造器」这回事——它随框架启动自动注册,无需 use 以外的任何初始化动作。
Db 类为什么不用 new 或 make
-
Db是门面(Facade),底层绑定的是think\db\Connection实例,由容器自动解析 - 你写
Db::table('user')->select(),实际调用的是容器中已准备好的连接实例,不是每次 new 一个新对象 - 即使没显式
use think\Db,在控制器或命令行中直接用也会触发自动加载(前提是命名空间正确) - 常见误操作:试图
new Db()→ 报错,因为Db没有公开构造函数;或app('db')手动取实例 → 不必要,且可能绕过配置参数(如读写分离设置)
use think\Db 是唯一必须写的代码
- 不写
use,又不在全局命名空间下,会报Class 'Db' not found - 错误示例:
<?php namespace app\controller; class User { public function index() { return Db::name('user')->select(); // ❌ 没 use,报错 } } - 正确写法:
<?php namespace app\controller; use think\Db; // ✅ 必须这一行 class User { public function index() { return Db::name('user')->select(); } }
助手函数 db() 的行为差异容易被忽略
-
db('user')是封装好的快捷方式,等价于Db::name('user') - 但它每次调用都会新建一个
Db实例(不是复用容器中的单例),导致:- 连接未复用,高并发下可能触发连接数超限
- 事务无法跨
db()调用延续(db('a')->startTrans()和db('b')->commit()互不感知)
- 所以:
- 单次简单查询可用
db('user')省几行代码 - 涉及事务、多次交互、性能敏感场景,必须用
Db::name('user')
- 单次简单查询可用
TP5 和 TP6 的 Db 兼容性断点
- TP5.1 中
Db::query()和Db::execute()可直接执行原生 SQL;TP6+ 统一收归到Db::raw()+ 查询构造器链式调用中,原生操作需显式走connection()->query() - TP6.3+ 默认关闭模型自动推导表名,但
Db::name('user')不受影响 —— 它本来就不依赖模型,只依赖配置里的prefix - 最容易踩的坑:把 TP5 的
where(['id' => ['in', $ids]])直接复制到 TP6,结果查不到数据,因为 TP6 把数组当成了id = ['in', $ids]字符串比较
真正要“加载”的,从来不是查询构造器本身,而是你对 Db 行为边界的认知。



















