Фильтрация элементов инфоблока по свойству в компонентах Bitrix
Предположим у нас есть список статей. Статья имеет свойство "Рубрика" (тип свойства - справочник) в котором соответственно выбирается название рубрики к которой относится статья.
Список статей на сайте выводится при помощи комплексного компонента Новости (bitrix:news).
Структура файлов компонента bitrix:news следующая:
// Путь до компонента, например:
// или /local/templates/ваш_шаблон_сайта/components/bitrix/news
// или /bitrix/templates/ваш_шаблон_сайта/components/bitrix/news
|- blogs/ # название папки шаблона компонента bitrix:news
| |- bitrix/
| |- images/
| |- lang/
| |- .parameters.php
| |- detail.php # файл в котором настраивается Детальная страница новости
| |- news.php # файл в котором настраивается страница общего Списка новостей
| |- rss_section.php
| |- rss.php
| |- search.php # файл для настройки страницы результатов поиска по новостям
| |- section.php # файл для настройки страницы раздела списка новостей
|
Так как фильтрация и сортировка элементов происходит в списках элементов, то нам нужно внести изменения в работу компонентов bitrix:news.list, который отвечает за вывод списка записей.
Список элементов выводятся на странице Общего списка новостей - news.php и на странице Раздела списка новостей - section.php.
Для фильтрации по нашему свойству Рубрика потребуется подготовить массив данных - содержащих название рубрики и xml_id ( для фильтрации по свойству типа справочник, нужно указывать xml_id фильтруемого значения ).
Чтобы подготовить нужный набор данных создадим в папке шаблона компонента файл result_modifier.php со следующим содержанием:
<?php if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
// Получаем массив $arResult['GROUP'] в котором содержатся данные об элементах свойства-справочника
if (CModule::IncludeModule('highloadblock')) {
$ID_GROUP = '1'; // ID highload-блока справочника
$hldata = Bitrix\Highloadblock\HighloadBlockTable::getById($ID_GROUP)->fetch();
$hlentity = Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hldata);
$hlDataClass = $hldata["NAME"] . "Table";
$result = $hlDataClass::getList(array(
"select" => array("ID", "UF_NAME", "UF_XML_ID", "UF_DESCRIPTION", "UF_FILE"), // Поля для выборки
"order" => array("UF_SORT" => "ASC"),
"filter" => array(),
));
while ($res = $result->fetch()) {
$arResult['GROUP'][] = $res;
}
}
// Функция для получения количества элементов в указанной рубрике
function getElementsCount($xml_id){
$rsData = CIBlockElement::GetList(
array('SORT' => 'ASC'),
array(
'IBLOCK_ID' => $arParams['IBLOCK_ID'],
'=PROPERTY_SECTION' => $xml_id // SECTION - символьный код свойства
),
false,
false,
array('NAME', 'IBLOCK_ID', 'CODE')
);
return $rsData->SelectedRowsCount();
}
Данные готовы. Теперь сделаем шаблон вывода фильтрации. Открываем для редактирования файл news.php. Перед 55 строкой ( перед вызовом компонента news:list ) добавим следующий код:
<div class="bx-news-list-filter-wrap">
<? foreach ($arResult['GROUP'] as $group):?>
<? if ($_GET['group'] != $group['UF_XML_ID']):?>
<a class="bx-news-list-filter-item" href="<?=$APPLICATION->GetCurPageParam("group=".$group['UF_XML_ID'], array("group"));?>">
<span class="bx-news-list-filter--text">
<span class="bx-news-list-filter-name"><?=$group['UF_NAME'];?></span>
<span class="bx-news-list-filter-count">(<?=getElementsCount($group['UF_XML_ID']);?>)</span>
</span>
</a>
<?else:?>
<div class="bx-news-list-filter-item active">
<span class="bx-news-list-filter-text">
<span class="bx-news-list-filter-name"><?=$group['UF_NAME'];?></span>
<span class="bx-news-list-filter-count">(<?=getElementsCount($group['UF_XML_ID']);?>)</span>
</span>
</div>
<?endif;?>
<?endforeach;?>
<? if ($_GET['group']):?>
<a class="bx-news-list-filter-item clear" href="<?=$APPLICATION->GetCurPageParam("", array("group"));?>">
<span class="bx-news-list-filter-name">Сбросить фильтр</span>
</a>
<?endif;?>
</div>
Кроме того обязательно перед вызовом компонента news.list так же добавим параметры для фильтрации ( именно этот код определяет работу фильтрации, передаёт параметры фильтра в компонент news.list )
Этот код ОБЯЗАТЕЛЬНО нужно размещать перед вызовом компонента news.list.
Код вывода списка значений свойства ( Рубрики ) можно выводить в любом месте страницы, в соответствии с Вашим дизайном.
<?
if ($_GET['group']):
// Задаём глобальный фильтр groupFilter
$GLOBALS['groupFilter'] = array(
'=PROPERTY_SECTION' => $_GET['group'] // SECTION - символьный код свойства
);
// Передаём имя глобального фильтра в настройки компонента news.list
$arParams["FILTER_NAME"] = 'groupFilter';
endif;
?>
Добавим стили для созданных элементов, для этого создадим в папке с шаблоном компонента файл style.css или если файл уже существует то добавим в него в конце следующие стили:
.bx-news-list-filter-wrap {
margin-left: -5px;
margin-right: -5px;
margin-bottom: 30px;
}
.bx-news-list-filter-item{
padding: 5px;
display: inline-block;
}
.bx-news-list-filter-item:hover{
text-decoration: none;
}
.bx-news-list-filter-text{
display: flex;
align-items: center;
font-weight: 400;
padding: 3px 10px 6px 10px;
background-color: #dddddd;
cursor: pointer;
border-radius: 5px;
transition: 0.3s ease background;
}
.bx-news-list-filter-item.active .bx-news-list-filter-text,
.bx-news-list-filter-item:hover .bx-news-list-filter-text{
background-color: #BBBBBB;
}
.bx-news-list-filter-item.clear .bx-news-list-filter-name{
color: #0065ff;
transition: 0.3s ease;
}
.bx-news-list-filter-item.clear:hover .bx-news-list-filter-name{
border-bottom: 1px dashed #0065ff30;
}
.bx-news-list-filter-name,
.bx-news-list-filter-count{
display: inline-block;
font-size: 13px;
line-height: 18px;
color: #333;
}
.bx-news-list-filter-count{
margin-left: 3px;
}
Получим вот такой стилизованный список рубрик для фильтрации:
Таким образом мы добавили функционал для фильтрации элементов по свойству типа справочник.
Это можно использовать к примеру для фильтрации товаров по производителю/бренду. Для этого нужно все те же самые действия произвести с комплексным компонентом Каталог bitrix:catalog. Код необходимо добавлять перед вызовом компонента списка товаров catalog.section.