Добрый день, при реализации фильтра объектов столкнулся с такой проблемой.
За основу взял
yii2-filter
Суть проблемы: Имеется фильтр/опция тип чекбокс
Работает по принципу фильтра объекта если в нём присутствует хотя бы одна из опций.
Выглядит всё это так (где item_id = id фильтруемого объекта)
ActiveRecord$filtered = FilterValue::find()->select('item_id')->groupBy('item_id')->andHaving("COUNT(DISTINCT `filter_id`) = $variantCount")->andFilterWhere($condition);
RawSqlSELECT `item_id` FROM `filter_value` WHERE (`filter_id`=2) AND (`variant_id` IN ('8', '12')) GROUP BY `item_id` HAVING COUNT(DISTINCT `filter_id`) = 1
Получается так, что если у объекта имеется хотя бы одна опция из этого фильтра, то он попадёт в результат выборки.
Нужно же что бы результаты выборки item_id выдавался только тех у кого присутствуют все выбранные варианты, в данном случае 8, 12.
Из того что приходит на ум это только такой вариант, но он мне не нравится.
RawSqlSELECT *, GROUP_CONCAT(variant_id) AS variant_ids FROM filter_value GROUP BY item_id HAVING LOCATE('8', variant_ids) AND LOCATE('12', variant_ids)
функция filtered вызываемая через behavior моделиpublic function filtered($filterIds = false, $mode = 0)
{
if(!$filterIds) {
$filterIds = Yii::$app->request->get($this->fieldName);
}
if(empty($filterIds)) {
return $this->owner;
}
$condition = ['OR'];
$variantCount = 0;
$filterCount = count($filterIds);
foreach($filterIds as $filterId => $value) {
$filter = Filter::findOne($filterId);
if($filter->type == 'range' && is_string($value)) {
$value = explode(';', $value);
if($value[0] != $value[1]) {
$variants = FilterVariant::find()->where('filter_id = :filterId AND (numeric_value >= :min AND numeric_value <= :max)', [':filterId' => $filterId, ':min' => $value[0], ':max' => $value[1]])->select('id')->all();
} else {
$variants = FilterVariant::find()->where('filter_id = :filterId AND numeric_value = :value', [':filterId' => $filterId, ':value' => $value[0]])->select('id')->all();
}
$variantIds = ArrayHelper::map($variants, 'id', 'id');
} else {
$variantIds = $value;
}
$condition[] = ['filter_id' => $filterId, 'variant_id' => $variantIds];
if($mode == 1) {
$variantCount += count($variantIds);
} else {
$variantCount++;
}
}
$filtered = FilterValue::find()->select('item_id')->groupBy('item_id')->andHaving("COUNT(DISTINCT `filter_id`) = $variantCount")->andFilterWhere($condition);
$modelClass = $this->owner->modelClass;
$tableName = $modelClass::tableName();
if ($filtered->count() > 0) {
$this->owner->andWhere([$tableName . '.id' => $filtered]);
} else {
$this->owner->andWhere([$tableName . '.id' => 0]);
}
return $this->owner;
}