Произвольное количество предложений whereHas - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть product с несколькими skus.Каждый sku имеет множество attributes.

Каждый атрибут имеет type, который может быть чем-то вроде "size" или "color", и value, который будет что-то вроде "M"или "черный".

У каждого продукта есть произвольное число attributes, которое я выбрал в форме для выбора.

Теперь у меня есть список каждого атрибута и его значения.

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

Отлично.Теперь мне нужно получить SKU, которые соответствуют этим конкретным атрибутам.

Например, это работает, когда у меня только один атрибут.

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

Но как мне построитьзапрос, который возвращает только те скусы, атрибуты которых соответствуют ВСЕМ квалификациям?

И помните, эти атрибуты произвольны по количеству.Я не могу жестко закодировать это;Мне просто нужно передать массив пар тип-значение.

Я выяснил, как это сделать вручную - но опять-таки он не учитывает произвольное количество атрибутов.Плюс, это неуклюже.Примерно так:

$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 голосов
/ 21 ноября 2018

То, как вы это сделали, кажется самым чистым способом сделать то, что вы просили.

Помните, что Eloquent - это просто абстракция 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...