Laravel中orWhereHas()不遵循where()条件的问题求助
问题分析与解决方案
你的代码核心问题是**orWhereHas破坏了查询的逻辑优先级**:SQL中AND的优先级高于OR,当前代码实际执行的逻辑是(原始条件 AND 关联indukbuku的条件) OR 关联distributor的条件,这会导致只要distributor的条件满足,就完全忽略qty<>0、id_faktur_konsinyasi以FKTKNST开头等原始约束。
修正后的代码
$q = $request->query('q'); $faktur = FakturKonsinyasi::with(['indukbuku', 'distributor']) ->where('qty', '<>', 0) ->where('id_faktur_konsinyasi', 'like', 'FKTKNST%') ->orderBy('id_faktur_konsinyasi', 'ASC'); if (!empty($q)) { // 先添加单据ID的模糊匹配 $faktur->where('id_faktur_konsinyasi', 'like', '%' . $q . '%'); // 仅当查询关键词不含FKTKNST时,才添加关联模型的筛选 if (!str_contains($q, 'FKTKNST')) { // 将关联筛选逻辑包裹在闭包中,确保和外部条件做AND运算 $faktur->where(function ($query) use ($q) { $query->whereHas('indukbuku', function ($subQuery) use ($q) { $subQuery->where('judul_buku', 'like', '%' . $q . '%'); })->orWhereHas('distributor', function ($subQuery) use ($q) { $subQuery->where('nm_distributor', 'like', '%' . $q . '%'); }); }); } } $faktur = $faktur->paginate(10);
关键修正点
- 逻辑分组:把两个
whereHas用where(function($query) { ... })包裹,让关联筛选逻辑作为一个整体,和外部所有条件执行AND运算,避免OR短路原始约束。 - 代码结构优化:将单据ID的模糊匹配提前,确保只要查询关键词不为空就执行该筛选,更贴合原始需求。
- 保留原有判断:继续使用
!str_contains($q,'FKTKNST')避免重复筛选(当关键词已经是单据ID前缀时,无需再匹配关联模型)。
可选优化
可以用Laravel提供的whereStartsWith方法替代like 'FKTKNST%',代码更直观:
->whereStartsWith('id_faktur_konsinyasi', 'FKTKNST')
内容的提问来源于stack exchange,提问作者raihanadf
相关产品推荐
相关产品推荐

