You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

关键修正点

  1. 逻辑分组:把两个whereHas用where(function($query) { ... })包裹,让关联筛选逻辑作为一个整体,和外部所有条件执行AND运算,避免OR短路原始约束。
  2. 代码结构优化:将单据ID的模糊匹配提前,确保只要查询关键词不为空就执行该筛选,更贴合原始需求。
  3. 保留原有判断:继续使用!str_contains($q,'FKTKNST')避免重复筛选(当关键词已经是单据ID前缀时,无需再匹配关联模型)。

可选优化

可以用Laravel提供的whereStartsWith方法替代like 'FKTKNST%',代码更直观:

->whereStartsWith('id_faktur_konsinyasi', 'FKTKNST')

内容的提问来源于stack exchange,提问作者raihanadf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 21:32:42