Laravel whereHas查询返回全部记录 如何按属性值过滤商品变体
错误原因说明
- 首次代码问题:
你写的whereHas关联是商品的属性值,whereIn逻辑是只要商品存在任意一个匹配的属性值就算符合条件,自然会返回当前商品的所有变体。另外还有两个低级错误:一是变量名拼写错误$poruduct_id,二是如果$value_ids是逗号分隔的字符串,直接套[$value_ids]会生成只有一个字符串元素的数组,无法正确匹配多个值。 - 第二次优化的问题:
你按product_id分组统计,统计维度是商品,还是没有绑定到变体本身的属性,所以筛选不出符合要求的变体。
可行解决方案
下面两种方案都可以实现需求:
方案一:SKU编码匹配(你最终采用的方案优化版)
修复你原有代码里的变量重复定义、未定义问题,简化匹配逻辑:
// 取请求参数 $product_id = $request->product_id; $value_codes = $request->value_codes; // 拆分编码为数组,过滤空值 $searchValues = preg_split('/,/', $value_codes, -1, PREG_SPLIT_NO_EMPTY); $variants = Variant::where(function ($q) use ($searchValues) { foreach ($searchValues as $value) { // 正则匹配确保不会命中其他编码的子串 $q->orWhereRaw('sku REGEXP ?', ["(^|-)${value}(-|$)"]); } }) ->where('product_id', $product_id) ->get(); dd($variants);
该方案性能高,只要SKU命名规则统一,比如属性编码之间用-分隔,就可以稳定使用。
方案二:关联查询精准匹配
如果不想依赖SKU规则,可以调整关联后查询:
首先给Variant模型添加和属性值的关联,再循环添加whereHas条件,要求变体满足所有指定的属性值:
$value_ids = explode(',', $request->value_ids); $product_id = $request->product_id; $variants = Variant::where('product_id', $product_id) ->where(function ($query) use ($value_ids) { foreach ($value_ids as $vid) { $query->whereHas('attributeValues', function ($q) use ($vid) { $q->where('value_id', $vid); }); } }) ->get(); dd($variants);
该方案灵活性更高,不需要约束SKU的命名规则。
内容的提问来源于stack exchange,提问作者Mehmet İMAL
相关产品推荐
相关产品推荐

