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

Laravel Eloquent 如何获取带过滤条件的Category-Subcategory-Product嵌套关联数据

问题场景

现有三级层级模型关联:Categories(一对多)Subcategories(一对多)Products,用于前端渲染可折叠商品列表,原始结构如下:

Category1
  - Subcategory1
    - Product1
    - Product2
Category2
  - SubCategory3
    - Product4

需求为搜索符合条件的商品(例:搜索Product1),同时保留分类->子分类->商品的层级结构,输出过滤后的结果:

Category1
 - Subcategory1
  - Product1

原有实现问题

最初使用whereHas查询仅能筛选出包含符合条件商品的分类,只会返回分类本身字段,不会加载关联的子分类、商品数据:

<?php
    $Categories = Categories::whereHas('subcategories', function ($q) use ($request) {
        $q->whereHas('products', function ($q) use ($request) {
            $q->where('name', 'LIKE', "%$request->search%")
              ->orWhere('article_number', 'LIKE', "%$request->search%");
        });
    })
    ->get();
?>

后续用资源类转换数据时,未对关联数据做预过滤,会查询出子分类下所有商品,不符合搜索需求。

最终解决方案

在查询时使用带条件的with预加载关联,同时配合whereHas过滤无符合条件商品的空分类、空子分类,最终代码如下:

$Categories = Categories::whereHas('subcategories', function ($q) use ($request) {
    $q->whereHas('products', function ($q) use ($request) {
        $q->where('name', 'LIKE', "%$request->search%")
            ->orWhere('article_number', 'LIKE', "%$request->search%");
    });
})->with(['subcategories'=> function ($q) use ($request) {
    $q->whereHas('products', function ($q) use($request) {
        $q->where('name', 'LIKE', "%$request->search%")
            ->orWhere('article_number', 'LIKE', "%$request->search%");
    })->with(['products'=>function ($q) use ($request) {
        $q->where('name', 'LIKE', "%$request->search%")
            ->orWhere('article_number', 'LIKE', "%$request->search%");
    }]);
}])->get();

逻辑说明

  1. 最外层whereHas保证只返回拥有符合搜索条件商品的分类,过滤空分类
  2. 预加载subcategories时加whereHas,保证只返回当前分类下拥有符合搜索条件商品的子分类,过滤空子分类
  3. 预加载products时加搜索条件,保证子分类下只返回符合搜索条件的商品

查询完成后直接使用原资源类转换数据即可,无需额外查询关联。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:06:03