PHP框架动态拼接查询条件须用Query Builder或参数绑定防SQL注入:Laravel用where闭包、when方法;ThinkPHP用多维数组;原生PDO需手动绑定参数,禁用字符串拼接。

PHP框架中动态拼接数据库查询条件时,必须避免SQL注入风险,不能直接用字符串拼接变量,需依赖框架提供的查询构建器或参数绑定机制。
使用Query Builder动态添加where条件
大多数现代PHP框架(如Laravel、ThinkPHP、CodeIgniter)都内置Query Builder,支持链式调用追加where条件。
第一步:初始化基础查询,例如获取用户表所有记录但暂不执行:$query = DB::table('users');
第二步:根据请求参数判断是否需要添加条件。比如前端传入status=active,则追加->where('status', 'active');若传入name=张三,再追加->where('name', 'like', '%张三%')。
立即学习“PHP免费学习笔记(深入)”;
第三步:多个条件可连续调用where,框架会自动用AND连接;若需OR逻辑,改用orWhere,但要注意括号优先级——【不加闭包包裹的orWhere可能破坏原有AND逻辑】。
最后一步:调用->get()或->first()触发执行,生成并运行安全的预处理SQL。
Laravel中用闭包组织复杂条件
当需要混合AND/OR、带括号分组或嵌套条件时,必须用闭包把逻辑封装起来。
方法一:用where闭包实现“状态为active且(姓名含关键词或邮箱匹配)”:
$query->where('status', 'active')<br> ->where(function ($q) use ($keyword) {<br> $q->where('name', 'like', "%{$keyword}%")<br> ->orWhere('email', $keyword);<br> });
这会生成WHERE status = ? AND (name LIKE ? OR email = ?),括号确保OR不污染外层AND。
方法二:用when方法按需插入条件,更简洁:
$query->when($request->filled('min_age'), function ($q) use ($request) {<br> return $q->where('age', '>=', $request->min_age);<br>})<br>->when($request->filled('city'), function ($q) use ($request) {<br> return $q->where('city', $request->city);<br>});
只要参数存在且非空,对应where才会生效,不用写一堆if判断。
ThinkPHP 6.x 的多维数组条件拼接
ThinkPHP支持将条件写成关联数组,自动解析为AND组合:
$where = [];<br>if (!empty($data['status'])) {<br> $where['status'] = $data['status'];<br>}<br>if (!empty($data['category_id'])) {<br> $where['category_id'] = $data['category_id'];<br>}<br>Db::name('article')->where($where)->select();
注意:数组键名即字段名,值即精确匹配内容;若需模糊查询,改用['name' => ['like', '%' . $keyword . '%']]这种二维数组语法。
这一步操作起来很简单,直接把文件拖进去就行。
原生PDO绑定参数手动拼接(慎用)
绕过框架直接写SQL时,绝对禁止"WHERE name = '$name'"这种拼接。
正确做法是先收集条件字段和值,分别存入两个数组:
$wheres = []; $params = [];<br>if (!empty($input['title'])) {<br> $wheres[] = "title LIKE ?";<br> $params[] = "%{$input['title']}%";<br>}<br>if (isset($input['is_top']) && $input['is_top'] == 1) {<br> $wheres[] = "is_top = ?";<br> $params[] = 1;<br>}
然后拼装WHERE子句:$sql = "SELECT * FROM posts WHERE " . implode(' AND ', $wheres);
最后用prepare→execute($params)执行,确保每个变量都走参数绑定。



















