Запрос Laravel hasMany, где строки с пользовательскими значениями

У меня есть следующие таблицы в моей БД:

TABLE_PRODUCTS
id
name

TABLE_VARIANTS
id
product_id
sku

TABLE_VARIANTS_PROPERTIES
id
variant_id
property_value_id

Я пытаюсь создать запрос для фильтрации продуктов. Допустим, я хочу показать только те товары, у которых есть варианты с property_value_id=1 и property_value_id=2.

Отношения: PRODUCTS -> hasMany -> VARIANTS -> hasMany -> VARIANTS_PROPERTIES.

Любые идеи?


ОБНОВИТЬ:

Я использовал ответ Александра Питерса. Вот мой код:

$query->whereHas('variants.properties.propertiesValues', function ($query) use ($variants) {
        $query->whereIn('value', $variants);
    });

Чтобы быть более конкретным, у меня есть еще одна таблица в моем запросе, которую я не указывал раньше. Этот запрос работает, но не так, как ожидалось. Что я хочу сделать, так это: получить все ПРОДУКТЫ, у которых есть PRODUCTS_VARIANTS, которые имеют PRODUCTS_VARIANTS_PROPERTIES, которые имеют PRODUCTS_PROPERTIES_VALUES в качестве активного фильтра (ВАРИАНТЫ). Я знаю все варианты - я использую для этого декартово произведение. Так, например, мне нужно получить все продукты, у которых есть варианты, которые имеют все значения из варианта в фильтре. Этот запрос работает, только если есть варианты только с 1 значением. Как я могу это решить? Я пытаюсь использовать foreach($variants as...), но безуспешно. Все еще не работает на 100%, как ожидалось.

ТАБЛИЦЫ:

TABLE_PRODUCTS
id
name

TABLE_PRODUCTS_VARIANTS 
id
product_id
sku

TABLE_PRODUCTS_VARIANTS_PROPERTIES
id
variant_id
property_value_id

TABLE_PRODUCTS_PROPERTIES_VALUES
id
value

Все возможные варианты активного фильтра находятся во вложенном массиве, например, у меня есть активный фильтр с цветом ЧЕРНЫЙ и КРАСНЫЙ и размером фильтра XS:

[
0 => [
    0 => Black
    1 => XS
  ]
1 => [
    0 => Red
    1 => XS
  ]
]

Мне нужно проверить значения из массива ВАРИАНТОВ в последней таблице TABLE_PRODUCTS_PROPERTIES_VALUES в значении столбца. Но у него должны быть оба значения (черный и XS)

Любые идеи?


ОБНОВЛЕНИЕ - РЕШЕНО

Хорошо, я наконец решил это. Вот мой код:

$query->whereHas('variants', function ($query) use ($variants) {
        $i = 1;
        foreach($variants as $variant)
        {
            if($i == 1) {
                $query->whereHas('properties', function($query) use ($variant) {
                    $query->whereHas('propertiesValues', function($query) use ($variant) {
                        $query->whereIn('value', $variant);
                    });
                }, '=', count($variant));
            } else {
                $query->orWhereHas('properties', function($query) use ($variant) {
                    $query->whereHas('propertiesValues', function($query) use ($variant) {
                        $query->whereIn('value', $variant);
                    });
                }, '=', count($variant));
            }

            $i++;
        }
    });

Есть идеи, как сделать его менее сложным? :)


person general666    schedule 13.09.2018    source источник


Ответы (1)


Вложенные операторы has или whereHas также могут быть построены с использованием "точечной" нотации. Например, вы можете получить все сообщения, в которых есть хотя бы один комментарий и один голос. Поэтому, если вы хотите запросить вложенные варианты_свойств продуктов, вы должны поместить их с точками 'relation1.relation2' в whereHas

$ids = [1,2];
$products = Product::whereHas('variants.variants_properties', function ($query) use ($ids) {
    $query->whereIn('property_value_id', $ids);
})->get();
person Alexandr Peters    schedule 13.09.2018
comment
Это не работает, потому что property_variant не JOINED, и вы спрашиваете, где - person general666; 13.09.2018
comment
Вам не нужно присоединяться к таблице, потому что whereHas отношения запросов. Это 100% рабочий код, который я использую для фильтрации атрибутов или категории продукта, который имеет отношения «многие ко многим». - person Alexandr Peters; 13.09.2018
comment
Может быть, я что-то упускаю, но где вы используете whereHas для таблицы TABLE_VARIANTS_PROPERTIES? Вы просто используете whereHas для TABLE_VARIANTS. Или генерация whereHas в запросе mysql? - person general666; 13.09.2018
comment
Варианты — это не таблица. ii - отношение многие ко многим. Я обновил свой ответ, чтобы показать, что вы можете поддерживать отношения. - person Alexandr Peters; 13.09.2018
comment
Извините, но это не работает для меня. Честно говоря, я не понимаю ваш ответ с отношением «многие ко многим». Может быть, это не работает, потому что в моем запросе гораздо больше отношений, но я просто хотел написать это здесь простым способом... - person general666; 13.09.2018
comment
Да, это работает, но все же есть одна проблема. Представьте, что в фильтре вы выбираете цвета ЧЕРНЫЙ и КРАСНЫЙ и размеры XS. Тогда у вас есть 2 варианта: ЧЕРНЫЙ-XS и КРАСНЫЙ-XS. Как я могу это решить. У меня есть все возможные варианты из активных фильтров, я просто борюсь с запросом... - person general666; 13.09.2018
comment
вы можете сделать это с помощью цикла foreach и проверить, имеет ли ваш фильтр одно и несколько значений. Таким образом, вы можете использовать where() или whereIn() для выбора точных продуктов из БД. - person Alexandr Peters; 13.09.2018
comment
@AlexandrPeters спасибо за ваш ответ. Именно так я пытаюсь целый день, но все еще не работаю должным образом. Я обновил свой вопрос. Буду очень признателен за любую помощь.... - person general666; 13.09.2018