Laravel复用查询构建器时where条件叠加的原因解析
Laravel查询构建器叠加where条件的原因及解决方法
问题场景
初始构建基础查询:
$query = MyModel::query()->where('status', 1);
期望基于该基础查询,分别统计不同type的数据量:
$result1 = $query->where('type', 1)->count(); $result2 = $query->where('type', 2)->count(); $result3 = $query->where('type', 3)->count();
但实际$result2和$result3结果不符合预期,通过toSql()输出原生SQL后发现条件被叠加:
select * from `my_table` where `status` = ? and `type` = ? select * from `my_table` where `status` = ? and `type` = ? and `type` = ? select * from `my_table` where `status` = ? and `type` = ? and `type` = ? and type = ?
原因分析
Laravel的查询构建器实例是可变对象,调用where()、orderBy()这类方法时,会直接修改原实例的查询条件,而不是返回一个全新的实例。
第一次调用$query->where('type', 1)后,原$query已经追加了type=1的条件;第二次调用$query->where('type',2)是在已修改的$query基础上继续追加,自然会出现多个type条件叠加的情况。
解决方法
方法一:克隆查询实例
每次基于基础查询扩展时,使用clone复制原实例,避免修改原对象的条件:
$query = MyModel::query()->where('status', 1); $result1 = (clone $query)->where('type', 1)->count(); $result2 = (clone $query)->where('type', 2)->count(); $result3 = (clone $query)->where('type', 3)->count();
方法二:一次性分组统计(更高效)
如果只是统计不同type的数量,推荐用分组查询一次性获取结果,减少数据库查询次数:
$counts = MyModel::query() ->where('status', 1) ->selectRaw('type, count(*) as total') ->groupBy('type') ->pluck('total', 'type'); // 获取对应type的数量:$counts[1]、$counts[2]、$counts[3]
内容的提问来源于stack exchange,提问作者Donny Akhmad Septa Utama
相关产品推荐
相关产品推荐

