Недавно при разработке очередного сайта столкнулся с проблемой фильтрации. Проблема заключается в том что битрикс даже для тех свойств у которых тип множественное позволяет выбрать значения, но фильтрация происходит по условии ИЛИ, иногда необходимо что бы фильтрация осуществлялась по И. Для тех кто не понял если я на примере luch.by часы могут иметь несколько характеристик, например водонепроницаемость и календарь, так вот при работе стандартного фильтра он выбирает в каталоге если я выберу эти два параметра одновременно, то поиск будет выдавать результаты у которых в свойствах есть либо календарь, либо водонепроницаемость, либо одно и другое свойство, а необходимо что у часов жостко было задано водонепроницаемость и календарь одновременно. Для тех кто столкнулся с данной проблемой предлагаю свой вариант решения.
Допустим в инфоблоке есть свойство "Дополнительные опции" в котором организован список множественного выбора, который мы хотим использовать в фильтре и имя данного свойства "DOP", нам нужно создать еще одно дополнительное поле "Контрольную строку" тип строка с именем допустим "DOP_CONTROL"
Далее в свойстве инфоблока указываем файл "Файл для редактирования элемента, позволяющий модифицировать поля перед сохранением" (Предварительно данный файл необходимо создать, допустим назовем данный файл "dop.php"). После этого оставляем в покое свойства инфоблока.
В файл "dop.php" поместим текст:
<?
//12 - код свойства Дополнительные опции
//39 - код свойства контрольная строка
if (count($PROP["12"])){ //проверяем было ли заполнено данное свойство
$str="";//в эту будет формироваться текст для контрольной строки
$dop=$PROP["12"];
sort($dop);// сортирую массив (можно и не фильтровать, для меня это более эстэтичнее)
foreach ($dop as $key=>$value)
{$str.="_{$value}_";}//далее формируется строка выбранных ID элементов списка
// на выходе получим строку типа "_42_50_30" в зависимости от выбранных параметров
foreach ($PROP["39"] as $key=>$value) $PROP["39"][$key]=$str;
// заполняем свойство для чего сделал это через цикл не помню возможно будет //достаточно $PROP["39"][0]=$str;
}
else foreach ($PROP["39"] as $key=>$value) $PROP["39"][$key]="";//обнуляем если ранее было заполнено
?>
Таким образом при каждом изменении либо добавлении элемента свойство "DOP_CONTROL" будет обновляться.
Далее работаем с публичной частью:
добавляем стандартный фильтр на станицу, копируем его, затем выбираем в настройках что будем фильтровать по свойству "DOP" и что имя фильтра - "filter".
Далее создаем и правим result_modifier.php, данного фильтра. Для множественного поля я думаю больше подойдут флажки, чем список где при помощи контрола и мышки нужно выбирать свойства ("Помните то что не высе такие умные как мы") . Для этого смодулируем флажки, также в коде модифицируем массив фильтра.
<?
// код приблизителен выдерал из кучи кода необходимого для работы других свойств
foreach($arResult["ITEMS"] as $key=>$item)
{
foreach($arResult["arrProp"] as $kk=>$prop)
if (($prop["NAME"]==$item["NAME"]) && ($prop["MULTIPLE"]=="Y") ) // я думаю любой программист разберется для чего это нужно, для лучшего понимания вывидите $arResult
{ $chek="";
$ID=$kk;//ID в массиве сгенерированного битриксом мы его заменим на чекбоксы
foreach ($prop["VALUE_LIST"] as $k=>$value )//здесь $k id в списке $value название свойства
{
if (in_array($k,$_GET["filter_pf"][$prop["CODE"]])) $dop=" CHECKED "; else $dop="";// проверяем было ли выбранно данное свойство, т.е фильтр по данному свойству установлен
$chek.="<input $dop name=\"filter_pf[{$prop["CODE"]}][]\" value=\"$k\" type=\"checkbox\"/>".GetMessage($k)."<br>";}
}
$arResult["ITEMS"][$key]["INPUT"]= $chek;// устанвливаем новое свойство
}
}
if (count($GLOBALS["filter"]["PROPERTY"]["DOP"])) // проверяем был ли установлен фильтр
{
$dop=$GLOBALS["filter"]["PROPERTY"]["DOP"]; // сохраняем в переменной
unset($GLOBALS["filter"]["PROPERTY"]["DOP"]);// уничтожаем старые значения, для того что бы не мешали
$str="";//строка будет формировать условия
sort($dop);//опять же я сортирую массив
foreach($dop as $val){
if (strlen($str)) $str.="&(%_{$val}_%)"; else $str.="(%_{$val}_%)"; //формирую строку для сложного поиска
}
//в итоге получается строка приблизительно такая (%_42_%)&(%_43_%).....
$GLOBALS["filter"]["?PROPERTY_DOP_CONTROL"]=$str;// устанвливаем новое значение фильтра уже для поля Контрольной строки
}
//?PROPERTY_DOP_CONTROL - значит что будет сложное условие про это можно почитать в двух слова здесь проверяется вхождение в контрольную строку сразу 42 и 43, посколько значения обрамлены "_" лишних элементов не выбирется % - любое количестов символов () - для условия & - оператор И
?>
Теперь нам осталось добавить список новостей, либо элементов каталога и указать там имя фильтра - "filter"
Вот и все проблема решена. Я думаю это лучше что мне предложила техподдрежка (сделать один запрос который достанет ID элементов по данному свойству, потом второй по другому..... т.д, а затем найти пересечение этих массивов и в результате массив пересечений вставить в еще один запрос, который сделает выборку по полученным ID - что и будет результатом), я думаю что предложенный вариант не эффективен, увеличивается количество запросов к базе и возможно если большая база можно и выйти за пределы памяти да и представьте какой длинны будет данный запрос.
Мою идею можно доработать, до компонента я думаю разработчики это могут сделать, для этого достаточно заполнять допустим поле "Описания", которое допустим используется для файлов, в это описание записывать контрольную строку. И обновить компонент для фильтра.
либо я задачу не понял, ректально как-то имхо. я делал так: свойство типа "список" с одним вариантом ответа, внешний вид - чекбокс. Дальше - дело техники.
P.S: печально конечно, что свойства Да/Нет до сих пор нет в инфоблоках
либо я задачу не понял, ректально как-то имхо. я делал так: свойство типа "список" с одним вариантом ответа, внешний вид - чекбокс. Дальше - дело техники.
P.S: печально конечно, что свойства Да/Нет до сих пор нет в инфоб
По поводу да/нет согласен. То что вы про коментировали можно сделать для админки, чекбоксы будут в админке, а на публичке нет, там будет простой список с множественным выбором (аналогичный при выборе раздела в инфоблоке).
Мою идею можно доработать, до компонента я думаю разработчики это могут сделать, для этого достаточно заполнять допустим поле "Описания", которое допустим используется для файлов, в это описание записывать контрольную строку. И обновить компонент для фильтра.
Реализовать предложенную схему в компонент сложновато, т.к. это частное решение, а компоненты решают глобальные )).
Подскажите, пожалуйста, как возможно реализовать систему фильтров как на или Необходимо фильтрация после выбора каждого свойства и должнен быть виден остаток товаров удовлетворяющих данному свойству.
Недавно сделал такой, сделал свой компонент. Смотри здесьhttp://www.luch.by/catalog/. Если будет интересно скину на почту компонент, в коде посмотрите как работает может разберетесь.
Добрый день! Буду признателен если кто-нибудь поделится компонентом. neon.rise@gmail.com Стоит очень похожая задача, а самому такое реализовать пока не по силам. Спасибо заранее!
Уважаеммые коллеги, в моем посте описано как это делается, и помоему достаточно подробно, однако поделится компонентом не смогу, т.к. компонент писался под определеный сайт и переписывался много раз в основном из-за медленной работы фильтра из-за чего пришлось завести на него самописный кэш, построил кэш на основании инфоблока (не очень хорошая идея, нужно было сделать быстро). Сдесь отображена основная идея, немного разобравшись поймете, что это не все так сложно, при минимальных знаниях jquery можно настороить ajax. Если совсем ничего не понятно, обращайтесь постараюсь ответить.
Активно изучаю битрикс, именно сейчас во всю занимаюсь фильтрами и безумно интересна Ваша реализация компонента, Дмитрий. Очень хочется разобраться как он работает. Если не затруднит скиньте, пожалуйста, на axel1703@list.ru !
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».