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

ThinkPHP 5.1 的 `where()` 方法**本身不自动防御字符串拼接型 SQL 注入**——关键看你怎么写。只要用了 `"字段=值"` 这类纯字符串条件且中间拼入用户输入,就等于主动关闭防护,和裸写 SQL 几乎一样危险。 真正安全的写法,是让框架识别出“这是参数”,从而触发 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')]——键名可控即高危。
绝对要避开的写法(高危!)
这些看着像用了 `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 字段等元数据,预处理无法保护,只能靠严格白名单或枚举。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











