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();
逻辑说明
- 最外层
whereHas保证只返回拥有符合搜索条件商品的分类,过滤空分类 - 预加载
subcategories时加whereHas,保证只返回当前分类下拥有符合搜索条件商品的子分类,过滤空子分类 - 预加载
products时加搜索条件,保证子分类下只返回符合搜索条件的商品
查询完成后直接使用原资源类转换数据即可,无需额外查询关联。
内容的提问来源于stack exchange,提问作者NLWork
相关产品推荐
相关产品推荐

