Laravel嵌套查询模糊匹配需用whereHas()而非with(),关联字段like条件须手动拼%;多字段用where分组+orWhere;多层关联需闭包嵌套;主表与关联表混合模糊搜索须将模糊条件置于外层where闭包内,精确条件放外层。

嵌套查询中对关联字段做模糊匹配
要在 Laravel 中通过主模型查出「满足关联表某字段模糊条件」的记录,必须用 whereHas() 显式声明存在性,不能在 with() 里加条件——后者只过滤预加载数据,不影响主模型结果集。
第一步:确认关联关系已正确定义。例如 Product 模型中需有 public function getProductItem() { return $this->hasMany(ProductItem::class, 'product_id'); }。
第二步:调用 whereHas(),传入关联名和闭包。闭包内使用标准 where('字段', 'like', "%{$keyword}%") 语法,【通配符 % 必须手动拼接,框架不会自动添加】。
第三步:若需同时匹配多个关联字段(如 sku 和 name),在同一个 whereHas 闭包内用 orWhere 连接,并用额外一层 where 分组包裹,防止逻辑外溢。
多层级嵌套关联的模糊搜索
当需要查「订单 → 订单商品 → 商品规格」三层关联中规格名含关键词的订单时,不能链式调用 whereHas→whereHas,而应逐层嵌套闭包。
方法一:单层深度嵌套
Order::whereHas('orderItems', function ($q) use ($k) { $q->whereHas('productVariant', function ($sub) use ($k) { $sub->where('name', 'like', "%{$k}%"); }); })->get();
方法二:同一层内匹配多个关联路径
Order::whereHas('orderItems', function ($q) use ($k) { $q->whereHas('product', function ($sub) use ($k) { $sub->where('name', 'like', "%{$k}%"); }) ->orWhereHas('productVariant', function ($sub) use ($k) { $sub->where('sku', 'like', "%{$k}%"); }); })->get();
注意:外层 whereHas 的闭包是必要分组边界,漏掉会导致 OR 条件脱离约束范围,使 status=1 等前置条件失效。
带主模型条件的混合模糊搜索
用户搜索时既想匹配订单号(主表 id),又想匹配商品名称(关联表字段),还要求订单状态为已支付——这三类条件必须分层组织,否则 SQL 逻辑必然错乱。
① 先将所有模糊条件(含主表字段和关联字段)统一收进一个外层 where 闭包;
② 在该闭包内,用 orWhere 把主表字段匹配(如 id、title)和 whereHas 关联匹配并列写;
③ 所有非模糊的精确筛选条件(如 status = 2、user_id = 123)必须写在这个闭包 之外,作为顶层 AND 条件;
④ 最后调用 paginate() 或 get(),确保分页统计包含全部 WHERE 逻辑。
示例代码结构:
Order::where('status', 2) ->where(function ($q) use ($k) { $q->where('id', $k) ->orWhere('sn', 'like', "%{$k}%") ->orWhereHas('orderItems.product', function ($sub) use ($k) { $sub->where('name', 'like', "%{$k}%"); }); }) ->paginate(20);


















