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

Laravel whereHas关联表多属性值同时匹配查询问题

问题根因

你当前多属性筛选返回空结果的核心原因是:在同一个whereHas闭包内连续对value_name做等值where判断,生成的SQL逻辑是要求单条attributes记录的value_name字段同时等于China和Grey,但单条属性记录仅会存储一个属性值,永远无法满足该条件,自然返回空结果。
从你给出的表数据可以看到,China、Grey是item_id=1的商品对应的两条独立属性记录,要匹配同时持有多个属性的商品,核心逻辑是统计商品关联的属性中命中所有目标值的记录数,等于传入的筛选属性总数量。

可直接复用的实现代码

该方案支持动态传入任意数量的属性筛选值,兼容单属性、多属性筛选场景:

// 动态传入的待筛选属性值数组,示例为['China', 'Grey'],可根据接口入参动态赋值
$targetAttributeValues = ['China', 'Grey'];

$products = Product::where('price', '>', 0)
    ->orderBy('price', 'asc')
    ->with('attributes')
    ->whereHas('attributes', function (Builder $query) use ($targetAttributeValues) {
        $query->whereIn('value_name', $targetAttributeValues)
            ->groupBy('item_id') // item_id为attributes表关联products表的外键,可根据实际表字段名调整
            ->havingRaw('COUNT(DISTINCT value_name) = ?', [count($targetAttributeValues)]);
    })
    ->get();
逻辑说明
  • 先通过whereIn筛出所有匹配任意一个目标属性值的关联记录
  • 按关联的商品ID分组,统计每个商品命中的不同属性值数量
  • 仅当命中数量等于传入的筛选属性总数时,判定该商品满足「同时持有所有指定属性」的要求
  • 单属性筛选时传入长度为1的数组即可兼容原有逻辑,不需要额外写判断分支

提示:如果你的attributes表不存在同一商品重复存储相同value_name的情况,可以去掉DISTINCT直接用COUNT(*)统计,查询性能会更好。

内容的提问来源于stack exchange,提问作者Александр Инженер

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:15:29