ThinkPHP 5.1 的 where() 方法本身不自动防御字符串拼接型 SQL 注入,安全依赖正确用法:必须使用占位符(如 %d、%s)配合参数传入,或采用数组条件触发 PDO 预处理绑定;严禁字符串拼接用户输入,动态字段/排序需白名单校验。

用占位符 + 数组/多参数传参(推荐)
TP5.1 支持 `%d`、`%s`、`%f` 等格式化占位符,配合数组或多个参数传入,框架会自动转义并绑定:✅ 安全示例:
$user->where("id=%d AND status='%s'", input('id'), input('status'))->find();$user->where("score>%f AND name='%s'", input('min_score'), input('name'))->select();$user->where("id=%d AND title LIKE '%s'", $id, '%' . input('kw') . '%')->select();
⚠️ 注意:单引号必须写在字符串里(如 '%s'),不能靠 PHP 拼进去;%s 会自动加引号,%d 自动转整型,%f 转浮点。
改用数组条件(最稳妥)
数组方式天然走参数绑定,无需记占位符规则,也更易读、易维护:✅ 安全示例:
$user->where(['id' => input('id'), 'status' => input('status')])->find();$user->where(['title' => ['like', '%' . input('q') . '%']])->select();$user->where(['score' => ['>', input('min_score')]])->select();
⚠️ 禁止这样写:['id' => input('id'), input('key') => input('val')]——键名可控即高危。
立即学习“PHP免费学习笔记(深入)”;
绝对要避开的写法(高危!)
这些看着像用了 `where()`,实则完全绕过绑定机制:-
where("id = " . input('id'))—— 字符串拼接,直接执行 -
where("title like '%" . input('q') . "%')—— 引号、通配符、值全由用户控制 -
where($field . " = ?", [$value])—— 字段名动态,PDO 不绑定字段名 -
where("status = " . input('s'))->order(input('sort') . ' ASC')—— order 里的字段名也无法参数化
这类写法哪怕只出现一次,就可能成为注入入口。
动态字段/排序/分组怎么办?
如果确实需要根据用户输入决定查哪个字段或怎么排序,**必须白名单校验**:✅ 示例:
$allowFields = ['id', 'name', 'email', 'create_time'];$field = in_array(input('sort'), $allowFields) ? input('sort') : 'id';$user->order($field . ' DESC')->select();
字段名、表名、排序方向、GROUP BY 字段等元数据,预处理无法保护,只能靠严格白名单或枚举。



















