查数据用db::query()返回数组,改数据用db::execute()返回影响行数;参数绑定只支持值(如:status),表名/字段名须白名单校验后拼接;事务中原生sql需确保可回滚,禁用非事务语句。

ThinkPHP 6 的 Db::query() 和 Db::execute() 怎么选
查数据用 Db::query(),改数据(INSERT/UPDATE/DELETE)用 Db::execute()。两者底层都走 PDO,但返回值和语义完全不同:Db::query() 返回二维数组,Db::execute() 返回影响行数(int),出错时都抛 think\db\exception\DataNotFoundException 或 PDO 异常。
常见错误是拿 Db::execute() 去查列表,结果得到一个数字,然后 foreach 报错;或者用 Db::query() 执行 UPDATE,看似“成功”,实际没生效(因为没走执行逻辑)。
- SELECT、SHOW、EXPLAIN 等只读语句 → 必须用
Db::query() - INSERT、UPDATE、DELETE、REPLACE → 必须用
Db::execute() - 带变量拼接的 SQL,务必用参数绑定,别直接字符串拼接
$id
原生 SQL 里的参数绑定怎么写才安全
ThinkPHP 不支持 ? 占位符自动识别字段名或表名,只支持值绑定。所以 WHERE id = ? 可以,但 ORDER BY ? 或 FROM ? 会直接报错或被当成字符串字面量。
正确做法是:值一律用 [:param] 占位 + 第二个参数传数组;表名/字段名/排序方向等动态部分,必须手动白名单校验后拼接。
Db::query("SELECT * FROM user WHERE status = :status AND name LIKE :name", [
'status' => 1,
'name' => "%{$keyword}%"
]);
-
:status和:name是命名占位符,对应数组键名 - 不要写成
? , [1, "%abc%"]—— ThinkPHP 6 不兼容问号位置绑定 - 如果要动态
ORDER BY,先判断$sortField是否在['id', 'create_time']里,再拼进 SQL 字符串
事务里执行原生 SQL 为什么有时不回滚
核心原因:PDO 默认开启 auto-commit,而 ThinkPHP 的事务管理依赖 Db::startTrans() → Db::commit()/Db::rollback() 这套流程。如果你在事务块里混用了原生 Db::query() 或 Db::execute(),只要没抛异常,框架就认为“执行成功”,不会主动中断事务。
更隐蔽的坑是:某些原生 SQL(比如 CREATE TEMPORARY TABLE、SET @var=1)在 MySQL 中不参与事务,即使在 startTrans() 之后执行,rollback() 也无效。
- 所有原生操作必须放在
Db::startTrans()之后、Db::commit()之前 - 每个
Db::query()/Db::execute()都要检查返回值或用 try-catch 捕获异常 - 避免在事务中执行非事务性语句(如
DROP TABLE、ALTER TABLE、变量赋值)
调试原生 SQL 时看不到真实执行语句怎么办
ThinkPHP 默认不记录原生 SQL 到日志,Db::getLastSql() 对 Db::query() 和 Db::execute() 都无效——它只对 Query Builder 有效。
想看真实执行的 SQL,有两个可靠办法:开 MySQL general_log,或在代码里手动拼接(仅用于调试)。
// 调试用:手动拼出带值的 SQL(切勿用于生产)
$sql = "SELECT * FROM user WHERE id = :id";
$bound = ['id' => 123];
$debugSql = strtr($sql, array_map(fn($v) => is_string($v) ? "'{$v}'" : (string)$v, $bound));
- 生产环境禁用字符串替换,防止 SQL 注入残留风险
- MySQL 的
general_log = ON最准,但 I/O 开销大,用完记得关 -
Db::getRealSql()不适用于原生方法,别白费劲
该踩的坑基本就这些。最麻烦的是动态字段+参数绑定混用,还有事务里夹带非事务语句——这两处一出问题,日志里往往没线索,得靠数据库层面抓包或开 general_log 才能定位。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










