我有一个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();
答案 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();