2020-09-24 07:24:00
ThinkPHP的数据库查询构造器通过链式调用和多种条件组合方式,能够灵活拼接复杂查询条件,尤其适用于动态生成SQL的场景。以下是具体实现方法及示例:
1. 使用where方法组合基本条件where()支持字符串、数组、闭包等多种格式,默认多个where条件为AND关系:
// 字符串格式$query->where('name', 'like', '%think%');// 数组格式(等值查询)$query->where(['status' => 1, 'type' => 2]);// 链式调用(AND关系)$query->where('status', 1)->where('score', '>', 80);生成SQL:WHERE status = 1 AND score > 80
2. 使用闭包实现嵌套条件(括号分组)闭包用于包裹子条件,自动添加括号形成独立逻辑块,解决类似(a=1 OR b=2) AND c=3的嵌套需求:
$query->where(function ($q) { $q->where('a', 1)->whereOr('b', 2); // (a=1 OR b=2)})->where('c', 3); // AND c=3生成SQL:WHERE (a = 1 OR b = 2) AND c = 3
3. 混合使用where与whereOr控制优先级链式调用中混用where和whereOr时,需注意AND/OR的优先级。若逻辑不明确,建议用闭包分组:
// 示例1:优先级问题(可能不符合预期)$query->where('status', 1) ->whereOr('score', '>', 90) ->where('deleted', 0);// 生成SQL:WHERE status = 1 OR score > 90 AND deleted = 0// 示例2:明确分组(推荐)$query->where(function ($q) { $q->where('status', 1)->whereOr('score', '>', 90);})->where('deleted', 0);// 生成SQL:WHERE (status = 1 OR score > 90) AND deleted = 04. 使用数组定义复合条件通过数组一次性定义复杂结构,适合配置化或动态构建查询:
$map = [ 'status' => 1, 'type' => ['in', [1, 2, 3]], function ($query) { $query->where('level', '>=', 5)->whereOr('vip', 1); }];$result = Db::name('user')->where($map)->select();生成SQL:WHERE status = 1 AND type IN (1, 2, 3) AND (level >= 5 OR vip = 1)
5. 结合exp表达式实现高级操作对于原生表达式或特殊函数,可用exp配合Db::raw()插入原始SQL片段(需注意SQL注入风险):
// 使用exp表达式$query->where('create_time', 'exp', Db::raw('BETWEEN 1609430400 AND 1609516800'));// 直接使用Db::raw()$query->whereExp('name', "LIKE '%test%' OR name LIKE '%demo%'");生成SQL:WHERE create_time BETWEEN 1609430400 AND 1609516800或WHERE name LIKE '%test%' OR name LIKE '%demo%'
关键技巧总结通过合理组合上述方法,可以清晰、安全地构建多层嵌套的复杂查询条件。