ThinkPHP 8.0查询构造器核心是获取未执行的think\db\Query实例,支持链式构建(where/order/field等)并复用,仅select()/find()/paginate()等末尾方法触发执行;Db::table()裸查,Db::name()尝试加载模型配置但不初始化。

在 ThinkPHP 8.0 中使用查询构造器,核心是获取一个未执行的 think\db\Query 实例,通过链式调用构建条件,最后用末尾方法(如 select()、find())触发执行。它不依赖模型类,轻量、灵活、可复用。
获取 Query 实例的两种方式
两种写法都返回可链式操作的 Query 对象,区别在于是否尝试加载模型配置:
- Db::table('user'):完全裸查,不关联任何模型,适合临时表、无模型映射或跨库场景
-
Db::name('user'):会尝试自动加载
app\model\User类(若存在),仅读取其连接、前缀等配置,不初始化模型逻辑;模型不存在时行为等同于table()
链式构建与安全复用
所有中间方法(where、order、limit、field 等)均返回自身,支持无限链式。关键原则是:只要没调用末尾方法,查询就未执行,对象可反复复用。
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 基础复用示例:$base = Db::table('log')->where('level', 'error'); 后续可分别执行
$base->where('env', 'prod')->select()和$base->date('created_at', '>=', '2026-01-01')->select() - 避免常见错误:不要在链中提前调
select()或find(),否则后续链式调用会报错或无效 - 排序注意字段存在性:连表或关联查询时,建议用
order('user.sort')而非order('sort')防止歧义
调试与原生 SQL 切换
调试阶段常需查看生成的 SQL,但又不想真正执行——这时用 buildSql():
- 调用
$query->buildSql()返回带?占位符的原生 SQL 字符串,例如SELECT * FROM `user` WHERE `status` = ? - 查看绑定参数用
$query->getBind(),它只返回显式绑定或隐式传入的值(如where('id', 123)中的123) -
buildSql()不执行 SQL,也不做参数转义,纯用于观察语句结构
分页必须从 Query 开始
ThinkPHP 的分页不是对结果集再加工,而是改写原始 SQL 加 LIMIT 和 COUNT 子查询,因此必须作用于未执行的 Query 实例:
- ✅ 正确:
Db::table('user')->where('status', 1)->paginate(15) - ❌ 错误:
Db::table('user')->where('status', 1)->select()->paginate(15)(select()已执行,返回数组,无法分页) - API 场景推荐传数组参数:
paginate(['list_rows' => 10, 'page' => input('page_no', 1), 'var_page' => 'page_no'])
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










