TP6的where()传字符串即裸奔,必须用数组、三元语法或闭包触发PDO预处理;原生SQL须用?占位符+参数数组,命名参数需手动启用params_bind;order/group等结构方法须白名单校验。

where() 传字符串就是裸奔,必须改用数组或闭包
TP6 的 where() 方法不自动防注入——它只在接收数组、三元语法(如 where('id', '>', $val))或闭包时才触发 PDO 预处理绑定;一旦传入字符串(哪怕加了单引号),就直接拼接进 SQL。
常见错误写法:
-
where("name = '" . input('name') . "'")→ 变量在双引号中被解析,'admin' OR '1'='1直接逃逸 -
where("status = " . input('status'))→ 数字型输入照样可拼1 UNION SELECT password FROM admin
安全写法(全部走绑定):
where(['name' => input('name'), 'status' => input('status')])-
where('name', input('name'))或where('status', 'eq', input('status')) where(function ($q) { $q->where('name', input('name'))->where('deleted', 0); })
原生 SQL 必须用 ? 占位符 + 参数数组,命名参数需显式启用
Db::query() 和 Db::execute() 本身不解析变量,但仅当 SQL 中含 ? 或命名参数(如 :id)且传入参数数组时,才触发绑定。命名参数在 TP6 默认配置下不生效,除非你手动开启 'params_bind' => true。
推荐写法(兼容性最强):
-
Db::query("SELECT * FROM user WHERE id > ? AND type = ?", [10, 'admin'])✅ -
Db::execute("INSERT INTO log (msg, created_at) VALUES (?, ?)", [$msg, date('Y-m-d')])✅
危险写法:
-
Db::query("SELECT * FROM {$table} WHERE id = " . $id)→ 表名和值双重不可信 -
Db::query("SELECT * FROM user WHERE name = :name", ['name' => $name])⚠️ 默认不生效,查日志会发现没 Binding 记录
order/group/having 等结构类方法必须白名单校验
这些方法不支持参数绑定,因为字段名、排序方向、聚合关键字属于 SQL 结构,不是数据值。PDO 不允许把 ORDER BY create_time DESC 的 DESC 当参数传。
必须做白名单过滤:
$sort = in_array(input('sort'), ['id', 'create_time', 'name']) ? input('sort') : 'id';$order = $sort . ' ' . (in_array(input('dir'), ['ASC', 'DESC']) ? input('dir') : 'DESC');-
order($order)→ 此时$order是已校验的纯字符串,无风险
反例:order('create_time ' . input('dir')) 允许传入 DESC, (SELECT password FROM admin),直接执行子查询。
验证是否真走了 PDO 绑定,不能只看日志里的 ?
TP6 日志显示 SQL: SELECT * FROM user WHERE id = ? 并不代表真的绑定了——它只是美化输出。底层可能因配置回退为字符串拼接。
确认真实绑定的三种方式:
- 开启
'sql_explain' => true和'debug' => true,查日志里是否有Binding: [123]这样的明确记录 - 用 Xdebug 断点跟到
think\db\Connection::execute(),确认调用了$pdoStatement->bindValue()而非execute($params) - 在 MySQL 开启
general_log,观察实际发往数据库的语句是WHERE id = ?还是WHERE id = 123—— 后者说明预处理被模拟或跳过
特别注意:Docker 环境或低版本 MySQL 下,PDO::ATTR_EMULATE_PREPARES 常被设为 true,此时即使代码写对了,也等于没绑。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











