Pull to refresh

Как сделать фильтр всех товаров на сайте по свойству, сохранив штатный функционал, и не сломав мозг?

Передо мной стояла следующая задача: сделать фильтрацию всех товаров в инфоблоке по одному свойству, сохранив штатный функционал и рабочий «Умный фильтр». Вы скажете, что в битриксе есть замечательный «умный» фильтр с его фасетными индексами, а я скажу, что да, он есть. Но давайте взглянем на исходные данные задачи:

1. У нас есть инфоблок, в корне которого лежат основные разделы

image

2. Фильтрация должна происходить по ссылкам с главной страницы

image

И так, у нас есть сразу 2 проблемы:

1. В битриксе нельзя вывести все товары из инфоблока, не указав определенный раздел инфоблока (как бы можно, но в настройках штатного компонента этого нет)
2. Как сделать ссылку на фильтр, если в запросе на фильтрацию подставляются какие-то левые значения (arrFilter_55_4161729085=Y&set_filter=Показать)?

Для более полного понимая способа решения данной задачи проделаю все шаги с самого начала на демо-сайте битрикса (https://bitrixlabs.ru/#create-demo).

Первым делом нужно создать отдельную страницу, на которой будет выводиться наш каталог с умным фильтром:

image
Специально выбрал фильтр по цвету, потому что цвет есть у нас во всех разделах сайта, как раз то, что нам нужно.

При переходе на созданную страницу мы видим список всех разделов инфоблока (а нам нужен список всех товаров из всех разделов данного инфоблока).

Копируем стандартный шаблон компонента «каталог», чтобы не портить стандартный + чтобы избежать возможных перезаписей шаблона после обновлений:

image

image

Теперь переходим к редактированию самого шаблона, а именно нам нужен файл «sections.php», удаляем в нем весь код и заменяем его на:

<?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

include "section_vertical.php";

?>


Здесь мы просто подключаем вертикальную секцию шаблона, чтобы у нас сразу выводился фильтр и список товаров без каких либо списков раздела. Вам может понадобиться подключить горизонтальную секцию, а может и вовсе оставить вывод списка разделов и сравнение товаров (в таком случае вам нужно будет скопировать из файла section_vertical.php код для вызова компонента умного фильтра и код для вызова компонента секции).

Смотрим что получилось:

image

Переходим к редактированию параметров компонента и выбираем нужный инфоблок:

image

Смотрим что получилось и ловим фиаско:

image

Переходим в редактирование параметров компонента и включаем умный фильтр (попутно выбираем нужные свойства для фильтрации и отключаем сайдбар и вывод дерева каталога):

image

Переходим к редактированию файла «section_vertical.php», ищем вызов компонента «bitrix::catalog.section» и добавляем ему к параметрам:

"SHOW_ALL_WO_SECTION" => "Y",


image

А вот пояснение к параметру из официальной документации:

image

Теперь переходим на нашу страницу с товарами и видим уже примерно следующее:

image
Список товаров выводится из всех разделов + фильтр на месте

Чуть не забыл, у фильтра в параметрах нужно отключить SEF_MODE (чпу), иначе работать наш фильтр не будет.

Остается теперь только понять алгоритм генерации ссылок для фильтра, как нам с главной страницы перейти по ссылке и чтобы фильтр автоматом подхватил ее и отфильтровал данные.

Смотрим что у нас передает фильтр после отправки формы:

image

Пробуем оставить только свойство цвета и переходим по полученной ссылке:

image
Все прекрасно работает

Остается понять алгоритм генерации данного параметра в запросе:

arrFilter_33_744714710

33 — это у нас ID свойства с цветом

image

А вот откуда тут берется 744714710 — не понято. Сначала я думал, что это может быть айдишкой самого значения свойства, но тут циферки для ID большие слишком + я все таки решил убедиться и проверил все это дело примерно таким способом:

$res =  CIBlockElement::GetList($arSort, $arFilter, false, false, $arSelect);
 
while($ob = $res->GetNextElement()){
        $arFields = $ob->GetFields();
        print_r($arFields);
}


Но там и рядом не было ничего с нужным нам значением. Тогда я решил заглянуть в исходники компонента умного фильтра и там нашел вот такой кусочек кода:

image

Собственно тут видно, что ключ фильтрации у нас генерируется за счет метода «fillItemValues»:

$this->fillItemValues($arResult["ITEMS"][$PID], $value)


Находим его в файле «class.php» с исходниками компонента умного фильтра (кто бы сомневался, хотя… битрикс же):

image

На 642 строке данного файла находим код, который и генерирует ключ фильтра:

$keyCrc = abs(crc32($htmlKey));

Получается, что тут просто высчитывается сумма из некого «htmlKey» и берется значение суммы по модулю

Находим происхождение «htmlKey» на строке 518:

$htmlKey = htmlspecialcharsbx($key);


Смотрим из чего у нас выходит «key»:

image

И видим, что при обычных раскладах это просто значение свойства.

Получается, что значение свойства хешируют и берут его значение по модулю + перед хеш суммой добавляется ID свойства.

Возвращаемся к моей изначальной задаче и делаем следующее:

$propValues = CIBlockElement::GetPropertyValues(8, array(), false, array("ID" => 55));//Получаем все значения свойства "производитель"
$pvalues = array();

while ($val = $propValues->Fetch()) {
	$pvalues[$val[55]] = abs(crc32($val[55]));
}


Перебираем все значения нужного нам свойства и записываем все это дело в ассоциативный массив.
А уже при выводе списка производителей просто ищем значение по уже готовому массиву:

<?if(!empty($pvalues[$arItem['NAME']])):?>
    <a href="/manufacturer/?arrFilter_55_<?=$pvalues[$arItem['NAME']]?>=Y&set_filter=Показать">
<?endif;?>
Тут html код вывода картинки производителя
<?if(!empty($pvalues[$arItem['NAME']])):?>
    </a>
<?endif;?>


Вауля и наш костыль готов к работе =)

При использовании данного метода есть свои нюансы, на странице с фильтром при выборе свойства фильтрации у нас всегда показывает 0 значений, хотя по факту там больше 0:

image

Но думаю, что если покопаться, то можно разобраться и с этим. В любом случае, данное решение лучше, чем просто выборка всех элементов через «GetList» и создание своего кастомного фильтра с нуля.

Надеюсь, что данная статья хоть кому-то облегчит жизнь и сэкономит пару часов,.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.