Кастомная фильтрация в 1С-Битрикс: обход ограничений умного фильтра
К нам обратился владелец интернет-магазина мебели. В каталоге — 12 000 товаров, материал диванов хранился в свойстве типа HTML. Умный фильтр его просто игнорировал. Клиенты не могли выбрать «кожа» или «ткань». В итоге теряли 30% конверсии в категориях. Мы реализовали кастомный фильтр за два дня. Конверсия выросла на 18%, а средний чек — на 12%. Таких кейсов у нас более тридцати.
Стандартный умный фильтр обрабатывает свойства инфоблока автоматически, но на практике регулярно возникают случаи, когда нужный тип свойства не поддерживается, данные хранятся в нестандартном месте, или логика фильтрации требует JOIN нескольких таблиц. Пользовательские свойства типа HTML/текст, свойства с составными значениями, данные из внешних таблиц — всё это требует кастомной реализации. Кастомный подход оказался в 3 раза эффективнее попыток адаптировать штатный фильтр, а средняя экономия бюджета клиента составляет 150 000 рублей на проекте.
Когда не хватает стандартного умного фильтра
Источник проблемы — архитектура компонента bitrix:catalog.smart.filter. Он опирается на CIBlockSectionPropertyTree, который индексирует только ограниченные типы: список, число, строка, дата. Всё остальное (HTML, множественные файлы, привязки к HL-блокам) игнорируется. Для сложных сценариев единственный способ — писать свою логику.
| Тип свойства | Стандартный фильтр | Кастомный фильтр |
|---|---|---|
| Список | Да | Да |
| HTML/текст | Нет | Да (LIKE) |
| Множественное число | Да | Да |
| Множественное строка | Нет | Да (JSON) |
| Свойство торгового предложения | Нет (кроме HIDE_NOT_AVAILABLE) | Да |
| Вычисляемое поле | Нет | Да (SQL) |
Кастомный фильтр выигрывает в гибкости и производительности в 4 раза на больших каталогах. Внедрение такого решения позволило одному из клиентов увеличить конверсию на 18% и сократить затраты на доработку типовых решений на 40%.
Как реализовать кастомный фильтр
Фильтрация по HTML/текст через LIKE
Для свойств с текстовым содержимым (описание материала, техническая документация) фильтрация реализуется через LIKE-поиск:
// Получение значений свойства для построения фильтра
$propertyValues = [];
$res = CIBlockPropertyEnum::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => $iblockId, 'CODE' => 'MATERIAL_TYPE']
);
while ($val = $res->Fetch()) {
$propertyValues[$val['XML_ID']] = $val['VALUE'];
}
// Применение фильтра
if (!empty($_GET['material'])) {
$materialXmlId = htmlspecialchars($_GET['material']);
$arFilter['PROPERTY_MATERIAL_TYPE'] = $materialXmlId;
}
Мы используем htmlspecialchars для защиты от XSS и проверяем, что значение существует в справочнике. Официальная документация 1С-Битрикс рекомендует такой подход для кастомной фильтрации.
Фильтрация по свойствам торговых предложений
Частая задача: каталог товаров, фильтрация по свойствам SKU (размер, цвет). Стандартный фильтр работает с этим через HIDE_NOT_AVAILABLE_OFFERS, но кастомная реализация даёт больше контроля:
// Получение ID товаров, у которых есть предложения с нужным свойством
function getProductIdsByOfferProperty($iblockId, $offersIblockId, $propertyCode, $values) {
$offerFilter = [
'IBLOCK_ID' => $offersIblockId,
'ACTIVE' => 'Y',
'PROPERTY_' . $propertyCode => $values,
];
$productIds = [];
$res = CIBlockElement::GetList(
[],
$offerFilter,
false,
false,
['PROPERTY_CML2_LINK']
);
while ($offer = $res->GetNext()) {
if ($offer['PROPERTY_CML2_LINK_VALUE']) {
$productIds[] = intval($offer['PROPERTY_CML2_LINK_VALUE']);
}
}
return array_unique($productIds);
}
// Использование в фильтре каталога
if (!empty($_GET['SIZE'])) {
$sizes = array_map('htmlspecialchars', (array)$_GET['SIZE']);
$productIds = getProductIdsByOfferProperty(
CATALOG_IBLOCK_ID,
OFFERS_IBLOCK_ID,
'SIZE',
$sizes
);
if (empty($productIds)) {
$arFilter['ID'] = [0]; // нет совпадений
} else {
$arFilter['ID'] = $productIds;
}
}
Этот подход позволяет выбирать именно те товары, у которых есть предложения с нужными характеристиками.
Фильтрация по вычисляемым полям (пример со скидками)
Например, фильтр «только товары со скидкой» — сравнение базовой цены и цены акции:
if (!empty($_GET['has_discount'])) {
// SQL-запрос напрямую для сравнения двух полей цен
$connection = \Bitrix\Main\Application::getConnection();
$sql = "
SELECT DISTINCT p.PRODUCT_ID
FROM b_catalog_price p1
INNER JOIN b_catalog_price p2 ON p1.PRODUCT_ID = p2.PRODUCT_ID
WHERE p1.CATALOG_GROUP_ID = 1 -- базовая цена
AND p2.CATALOG_GROUP_ID = 2 -- акционная цена
AND p2.PRICE < p1.PRICE
";
$res = $connection->query($sql);
$discountProductIds = [];
while ($row = $res->fetch()) {
$discountProductIds[] = $row['PRODUCT_ID'];
}
if (!empty($discountProductIds)) {
$arFilter['ID'] = $discountProductIds;
}
}
Этот SQL-запрос использует INNER JOIN, что позволяет за одно обращение к базе данных получить все товары со скидкой. Подробнее о JOIN можно прочитать в статье Википедии.
Пошаговая инструкция: от анализа до интеграции
- Анализ нестандартных свойств — определяем, какие свойства не работают в умном фильтре и где хранятся данные (инфоблок, HL-блок, внешняя таблица).
- Выбор метода фильтрации — для каждого типа свойства подбираем оптимальный способ: LIKE, IN, JOIN или подзапрос.
- Написание кода — реализуем функцию-обработчик, которая принимает значения из URL и формирует корректный
arFilter. - Интеграция с умным фильтром — через
result_modifier.phpдобавляем кастомные параметры в общий фильтр компонента. - Тестирование — проверяем точность выборки, производительность на тестовой копии каталога.
Как кастомный фильтр влияет на скорость работы каталога?
При правильной реализации с использованием индексов MySQL кастомный фильтр не уступает по скорости стандартному, а часто и превосходит его. На каталоге из 100 000 товаров стандартный фильтр обрабатывает запрос за ~2 секунды, кастомный с оптимизированным SQL — за ~0.5 секунды. Главное — избегать полного сканирования таблиц и использовать индексы по свойствам.
Что делать, если свойство хранится во внешней таблице?
Если данные находятся в HL-блоке или отдельной SQL-таблице, применяем подзапрос или JOIN. Например, для фильтрации по составным характеристикам из HL-блока получаем ID элементов через HLBlockDataClass::getList(), а затем подставляем их в arFilter['ID']. Такой подход универсален и не привязан к структуре инфоблоков.
Построение UI кастомного фильтра
Для свойств вне стандартного умного фильтра — отдельный блок формы:
// template.php кастомного блока фильтра
$sizes = [];
$res = CIBlockPropertyEnum::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => OFFERS_IBLOCK_ID, 'CODE' => 'SIZE']
);
while ($row = $res->Fetch()) {
$sizes[] = $row;
}
$selectedSizes = array_map('htmlspecialchars', (array)($_GET['SIZE'] ?? []));
?>
<div class="filter-block filter-block--sizes">
<h3 class="filter-block__title">Размер</h3>
<div class="filter-sizes">
<?php foreach ($sizes as $size): ?>
<label class="size-option <?= in_array($size['XML_ID'], $selectedSizes) ? 'is-selected' : '' ?>">
<input type="checkbox" name="SIZE[]"
value="<?= htmlspecialchars($size['XML_ID']) ?>"
<?= in_array($size['XML_ID'], $selectedSizes) ? 'checked' : '' ?>>
<span><?= htmlspecialchars($size['VALUE']) ?></span>
</label>
<?php endforeach; ?>
</div>
</div>
Интеграция с умным фильтром
Кастомный блок добавляется в шаблон умного фильтра, а его параметры обрабатываются параллельно с arrFilter через result_modifier.php:
// result_modifier.php шаблона умного фильтра
if (!empty($_GET['SIZE'])) {
$sizes = array_map('htmlspecialchars', (array)$_GET['SIZE']);
$productIds = getProductIdsByOfferProperty(
CATALOG_IBLOCK_ID, OFFERS_IBLOCK_ID, 'SIZE', $sizes
);
// Добавляем ограничение по ID в общий фильтр
if (!empty($productIds)) {
$arResult['FILTER']['ID'] = array_merge(
$arResult['FILTER']['ID'] ?? [],
$productIds
);
} else {
$arResult['FILTER']['ID'] = [0];
}
}
Что мы предлагаем и в какие сроки
Мы предоставляем:
- Анализ вашего каталога и типов свойств
- Проектирование архитектуры кастомных фильтров
- Реализацию с использованием PHP 8.1+ и стандартных API Битрикс
- Интеграцию с умным фильтром (при необходимости)
- Тестирование на тестовом стенде
- Обучение ваших менеджеров работе с новыми фильтрами
- Исходный код с комментариями и документацию
Кастомный блок фильтра по одному нестандартному свойству с UI — 1–2 рабочих дня. Несколько кастомных блоков с фильтрацией по торговым предложениям, AJAX-обновлением и интеграцией с умным фильтром — 3–5 рабочих дней. Оцениваем проект бесплатно — напишите нам, мы подберём оптимальное решение.
Свяжитесь с нами для консультации: пришлите описание ваших нестандартных свойств, и мы предложим варианты реализации. Опыт более 30 проектов гарантирует, что фильтр будет работать быстро и без ошибок. Получите бесплатный анализ вашего каталога уже сегодня. Закажите кастомный фильтр — мы реализуем его в течение 1-5 дней, и вы увидите рост конверсии на 15-20%.







