Фильтр выборки товаров по свойствам

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
vv-off
Сообщения: 56
Зарегистрирован: 2018.01.12, 11:49

Фильтр выборки товаров по свойствам

Сообщение vv-off »

Всем привет.
Ребята подскажите как можно реализовать. Есть таблица продуктов (product), таблица свойств (product_property), таблица значений свойств (product_property_value). Связи в моделях настроены. Вывожу всё это дела в модели фильтра:

Код: Выделить всё

$query = Product::find()
            ->joinWith([
                'productCategory',
                'productPrice.priceType',
                'photo',
                'property',
                'property.propertyName',
                'property.propertyValue',
                'product'])->distinct()
            ->where(['product_category.id' => $idCategory]);
Затем принимаю параметры $this->load($params);
и добавляю фильтры:

Код: Выделить всё

$query->andFilterWhere(['product_property_value.value' => $this->collection])
        ->andFilterWhere(['product_property_value.value' => $this->model])
        ->andFilterWhere(['product_property_value.value' => $this->color]);
Во view фильтра

Код: Выделить всё

 <?php $form = ActiveForm::begin([
        'method' => 'get',
    ]); ?>

    <?php echo $form->field($model, 'collection')->label('Коллекция') ?>
    <?php echo $form->field($model, 'model')->label('Модель') ?>
    <?php echo $form->field($model, 'color')->label('Цвет') ?>

    <div class="form-group">
        <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
    </div>

    <?php ActiveForm::end(); ?>
В итоге без фильтров выводится все корректно, при заполнении одного из фильтров так же все корректно, если добавляю заполнено больше одно фильтра, то ничего не находит. Происходит это понятно из-за where в запросе такого вида:

Код: Выделить всё

SELECT COUNT(*)
FROM (
    SELECT DISTINCT product.* 
    FROM product 
    LEFT JOIN product_category_matching ON product.id = product_category_matching.id_product 
    
    LEFT JOIN product_category ON product_category_matching.id_category = product_category.id 
    LEFT JOIN product_price ON product.id = product_price.id_product 
    LEFT JOIN price_type ON product_price.id_price_type = price_type.id 
    LEFT JOIN photo ON product.id = photo.id_product 
    
    LEFT JOIN product_property_matching ON product.id = product_property_matching.id_product 
    LEFT JOIN product_property ON product_property_matching.id_property = product_property.id 
    LEFT JOIN product_property_value ON product_property_matching.id_property_value = product_property_value.id 
    
    LEFT JOIN product sub_product ON product.article_site = sub_product.article_site
    
    WHERE (product_category.id=3) AND (product_property_value.value='Лето') AND (product_property_value.value='Бейсболка') AND (product_property_value.value='Белый')) c
Помогите, как изменить чтобы заработало... я в тупике ((( Куда копать? А точнее как исправить запрос чтобы по одной таблице значений свойств выбирались продукты у которых комбинация свойств найдена. In не подходит.
vv-off
Сообщения: 56
Зарегистрирован: 2018.01.12, 11:49

Re: Фильтр выборки товаров по свойствам

Сообщение vv-off »

Работает запрос вот такого вида:

Код: Выделить всё

SELECT COUNT(*)
FROM (
    SELECT DISTINCT product.* 
    FROM product 
    LEFT JOIN product_category_matching ON product.id = product_category_matching.id_product 
    
    LEFT JOIN product_category ON product_category_matching.id_category = product_category.id 
    LEFT JOIN product_price ON product.id = product_price.id_product 
    LEFT JOIN price_type ON product_price.id_price_type = price_type.id 
    LEFT JOIN photo ON product.id = photo.id_product 
    
    LEFT JOIN product_property_matching ppm_collection ON product.id = ppm_collection.id_product 
    LEFT JOIN product_property pp_collection ON ppm_collection.id_property = pp_collection.id 
    LEFT JOIN product_property_value ppv_collection ON ppm_collection.id_property_value = ppv_collection.id 
    
    LEFT JOIN product_property_matching ppm_model ON product.id = ppm_model.id_product 
    LEFT JOIN product_property pp_model ON ppm_model.id_property = pp_model.id 
    LEFT JOIN product_property_value ppv_model ON ppm_model.id_property_value = ppv_model.id 
    
    LEFT JOIN product_property_matching ppm_color ON product.id = ppm_color.id_product 
    LEFT JOIN product_property pp_color ON ppm_color.id_property = pp_color.id 
    LEFT JOIN product_property_value ppv_color ON ppm_color.id_property_value = ppv_color.id 
    
    
    
    LEFT JOIN product sub_product ON product.article_site = sub_product.article_site
    
    WHERE (product_category.id=3) AND (ppv_collection.value='Лето') AND (ppv_model.value='Бейсболка') AND (ppv_color.value='Белый')) c
Но как его реализовать и кажется выполняется он как-то долго...
vv-off
Сообщения: 56
Зарегистрирован: 2018.01.12, 11:49

Re: Фильтр выборки товаров по свойствам

Сообщение vv-off »

В общем прихожу к выводу, что бд нужно перестраивать (((...
skynin
Сообщения: 400
Зарегистрирован: 2017.12.12, 10:09

Re: Фильтр выборки товаров по свойствам

Сообщение skynin »

Вначале надо написать SQL запросы вручную

Перед этим погуглить о хранении и выборке по свойствам товаров. Тема затасканная, способов реализации много.

Однозначно вот так
ppv_model.value='Бейсболка'
не годится.

Будет медленно. Свойства должны быть сведены в таблицу значений свойств, чтобы искать по id значения, а не самому значению

Общий подход - надо делать эффективный запрос по таблице свойств, а только потом выбирать товары
так как нам надо выбирать по свойствам, то и первой таблицей должна быть она, а не товары.
Или подзапрос по ней, с результатами которого inner join.
или еще какой right join, зависит от схемы БД
Не желайте странного, и не будет у вас головной боли чтобы достичь этого странного.
Тем более что окажется что оно вам и не нужно было, странное это.
Ответить