Laravel Eloquent多条件关联查询:如何实现多属性同时筛选?
问题描述
我有一个inventory表,它与data表是一对多关联。正在开发筛选应用,用户可按颜色、材质等筛选库存,这些信息存储在data表以保证兼容性。
data表用于灵活扩展库存数据,字段如下:
inventory_id key value
需求:当用户筛选材质为棉且颜色为蓝色的库存时,仅返回同时满足两个条件的结果。
当前问题:现有查询返回的是材质为棉或颜色为蓝色的库存,代码如下:
$values = array_merge($materialValues, $colorValues); Inventory::query()->whereHas('data', function ($q) { return $q->whereIn('key', [ Enum::MATERIAL->key, Enum::COLOR->key ])->whereIn('value', $values); })
尝试过以下写法,但查询报错:
Inventory::query()->whereHas('data', function ($q) { return $q->where('key', Enum::MATERIAL->key) ->whereIn('value', $materialValues) ->where('key', Enum::COLOR->key) ->whereIn('value', $colorValues); })
需要保持查询为Builder实例,以便调用paginate()方法,请问用Eloquent能否实现该需求?
解决方案
可以实现,核心思路是对每个筛选维度单独调用whereHas——whereHas本身是AND逻辑,每个whereHas对应库存必须存在一条符合该维度条件的data记录,叠加后就能实现“同时满足所有筛选条件”的需求,且全程保持Builder实例可用。
示例代码:
$query = Inventory::query(); // 添加材质筛选条件 if (!empty($materialValues)) { $query->whereHas('data', function ($q) use ($materialValues) { $q->where('key', Enum::MATERIAL->key) ->whereIn('value', $materialValues); }); } // 添加颜色筛选条件 if (!empty($colorValues)) { $query->whereHas('data', function ($q) use ($colorValues) { $q->where('key', Enum::COLOR->key) ->whereIn('value', $colorValues); }); } // 调用分页,保持Builder实例特性 $results = $query->paginate(10);
原写法问题说明
- 第一种写法用
whereIn('key', [...])+whereIn('value', [...]),本质是匹配单条data记录满足“key是材质/颜色且value在合并数组中”,只要有一条记录符合任一条件就会被选中,因此出现OR的效果。 - 第二种写法在同一个
whereHas里同时要求key等于材质和颜色,单条data记录不可能同时满足两个不同的key值,因此会返回空结果或报错。
内容的提问来源于stack exchange,提问作者racinne
相关产品推荐
相关产品推荐

