whereHas子句的任意数量

时间:2018-11-20 23:01:04

标签: laravel laravel-5 eloquent

我有一个product和几个skus。每个sku有很多attributes

每个属性都有一个type,可能是“ size”或“ color”,另一个是value,可能是“ M”或“ black”。

每个产品都有任意数量的attributes,我已经选择了一种形式。

现在,我有每个属性及其值的列表。

[
    'size' => 'M',
    'color' => 'black',
]

太好了。现在,我必须获取与这些特定属性相对应的SKU。

例如,当我只有一个属性时,此方法有效。

$product->skus->whereHas('attributes', function($query) {
    return $query->where(['type' => 'size', 'value' => 'M']);
})->get();

但是如何构建仅返回具有与所有资格匹配的属性的skus的查询?

请记住,这些属性在数量上是任意的。我无法对其进行硬编码;我只需要传递类型-值对的数组即可。

我想出了如何手动执行此操作–但同样,它不允许使用任意数量的属性。另外,它笨重。像这样:

$product->skus->whereHas('attributes', function($query) {
    return $query->where(['type' => 'size', 'value' => 'M']);
})->whereHas('attributes', function($query) {
    return $query->where(['type' => 'color', 'value' => 'white']);
})->get();

编辑:以下代码似乎可以正常工作,但是笨拙。必须有更好的方法吗?

$list = $this->skus()->with('attributes');
foreach ($attrs as $type => $value) {
    $list->whereHas('attributes', function ($query) use ($type, $value) {
        return $query->where(['type' => $type, 'value' => $value]);
    });
}
return $list->first();

1 个答案:

答案 0 :(得分:0)

您完成的方式似乎是您所要求的最干净的方式。

请记住,口才是SQL的抽象。

如果您使用SQL编写此代码,则类似于:

select * from skus
where exists (select * from attributes where sku_id = skus.id and type = ? and value = ?)
and exists (select * from attributes where sku_id = skus.id and type = ? and value = ?)
and exists (select * from attributes where sku_id = skus.id and type = ? and value = ?)
...

从本质上讲,这是您对Eloquent所做的事情:

$list = $this->skus()->with('attributes');
foreach ($attrs as $type => $value) {
    $list->whereHas('attributes', function ($query) use ($type, $value) {
        return $query->where(['type' => $type, 'value' => $value]);
    });
}
return $list->first();