Умный фильтр (catalog.smart.filter) и список товаров (catalog.section) — два разных компонента, которые обязаны «видеть» друг друга. Когда фильтр выносят во включаемую область, эта связь легко ломается. Разбираем, как вынести фильтр в отдельный шаблонный блок и не потерять фасетный индекс, AJAX и ЧПУ.
Зачем выносить фильтр из шаблона компонента
По умолчанию комплексный компонент bitrix:catalog выводит умный фильтр внутри шаблона раздела — там, куда его поставил разработчик темы. Но в реальных проектах фильтр часто нужен в другом месте вёрстки: в левой колонке, которая формируется общим шаблоном сайта, в «липкой» боковой панели, в мобильной шторке или сразу на нескольких типах страниц (каталог, поиск, посадочные).
Держать разметку фильтра прямо в шаблоне catalog.section в таких случаях неудобно: она жёстко привязана к одному компоненту и одному месту. Гораздо чище вынести вызов catalog.smart.filter во включаемую область — отдельный файл, который подключается там, где нужно колонке, а не там, где стоит список товаров.
- фильтр переиспользуется на разных страницах без копипаста;
- вёрстка колонки и вёрстка товаров развязаны и правятся независимо;
- можно управлять кэшированием фильтра отдельно от списка.
Как фильтр связан со списком товаров
Ключевой момент, который ломает большинство таких переносов: catalog.smart.filter и catalog.section — независимые компоненты. Фильтр не выбирает товары сам. Он лишь формирует условия отбора и сохраняет их в глобальную переменную по имени, заданному в параметре FILTER_NAME. Список товаров затем читает эту переменную и применяет её к выборке.
Поэтому оба компонента обязаны использовать одно и то же значение FILTER_NAME (обычно arrFilter) и один и тот же элемент инфоблока — IBLOCK_TYPE, IBLOCK_ID и SECTION_ID / SECTION_CODE. Если фильтр выводит характеристики одного инфоблока, а список показывает другой раздел, вы получите «пустой» фильтр или отбор без результатов.
bitrix:catalog эта связка настроена автоматически. Вынося фильтр вручную, вы берёте ответственность за совпадение параметров на себя.Куда именно выводить: варианты включаемой области
В Битрикс «включаемая область» — это либо отдельный физический файл (например /include/catalog_filter.php), который подключают через $APPLICATION->IncludeFile(), либо стандартный компонент bitrix:main.include. Под задачу с фильтром подходят два подхода.
| Подход | Когда уместен |
|---|---|
Вызов catalog.smart.filter прямо в шаблоне сайта (в template.php или в области колонки) | Фильтр нужен на всех страницах каталога с одинаковыми параметрами |
Отдельный include-файл, подключаемый через IncludeFile | Разметку колонки редактируют контент-менеджеры или фильтр включается точечно |
Важно: где бы вы ни разместили вызов фильтра, он должен отработать раньше, чем список товаров прочитает переменную отбора. На практике фильтр в левой колонке шаблона выполняется до $APPLICATION->IncludeComponent с каталогом в рабочей области — это естественный порядок и обычно проблем не создаёт.
Пример вызова фильтра во включаемой области
Минимальный вызов компонента фильтра в файле колонки выглядит так:
$APPLICATION->IncludeComponent('bitrix:catalog.smart.filter', 'ВАШ_ШАБЛОН', array('IBLOCK_TYPE' => 'catalog', 'IBLOCK_ID' => 5, 'SECTION_ID' => $curSectionId, 'FILTER_NAME' => 'arrFilter', 'PRICE_CODE' => array('BASE'), 'CACHE_TYPE' => 'A', 'SEF_MODE' => 'Y', 'SEF_RULE' => '/catalog/#SECTION_CODE#/filter/#SMART_FILTER_PATH#/apply/'));
На что обратить внимание:
SECTION_ID— фильтр должен знать текущий раздел. В включаемой области его не всегда легко получить, поэтому раздел определяют по ЧПУ черезCIBlockSection::GetListили передают из основного компонента каталога;FILTER_NAMEстрого совпадает со списком товаров;SEF_MODEиSEF_RULEнужны, если используете ЧПУ-адреса фильтра — правило должно совпадать с настройками комплексного компонента.
Как получить текущий раздел в области
Главная сложность выноса — определить SECTION_ID текущей страницы каталога внутри включаемой области, которая сама не знает, какой раздел открыт. Есть три рабочих способа.
- Передать через переменную. Комплексный компонент каталога кладёт данные раздела в результат; можно сохранить
$arResult['VARIABLES']['SECTION_ID']в глобальную переменную и прочитать её в области. - Разобрать ЧПУ. Взять
$APPLICATION->GetCurPage(), вычленить символьный код раздела и найти его черезCIBlockSection::GetListпоSECTION_CODE. - Единый шаблон. Если структура URL стабильна, определить раздел один раз в
init.phpили в прологе и переиспользовать.
Первый способ надёжнее: вы используете тот же раздел, что и список товаров, и исключаете рассинхрон. Разбор ЧПУ проще, но чувствителен к вложенности разделов и мультирегиональности.
Кэш, фасетный индекс и AJAX
Вынос фильтра не отменяет его механику. Скорость по-прежнему держится на фасетном индексе — его нужно построить в настройках инфоблока (вкладка «Свойства» → «Фасетный индекс») и держать актуальным. Без него фильтр на большом каталоге будет тормозить независимо от места вывода.
Кэширование задаётся параметром CACHE_TYPE. Помните: кэш фильтра во включаемой области живёт отдельно от кэша списка товаров, и его нужно сбрасывать при изменении свойств или разделов. Автоматический сброс работает через теги кэша, если включена CACHE_GROUPS и корректно настроено управляемое кэширование.
Если фильтр должен обновлять список без перезагрузки страницы, параметр AJAX_MODE и связка через AJAX_ID должны совпадать с настройками компонента catalog.section. При выносе фильтра в чужой шаблон именно AJAX ломается чаще всего: фильтр в одном контейнере, список — в другом, и скрипт не находит цель обновления.
Типовые ошибки и как их избежать
- Фильтр пустой. Не совпадают
IBLOCK_IDили не построен фасетный индекс. Проверьте инфоблок и пересчитайте индекс. - Фильтр показывается, но не фильтрует. Разные
FILTER_NAMEу фильтра и списка. Приведите к одному значению. - Отбор не применяется на нужном разделе. Неверный
SECTION_IDв области — фильтр берёт свойства не того раздела. - Слетают ЧПУ фильтра.
SEF_RULEв области не совпадает с правилом комплексного компонента. - AJAX перезагружает всю страницу. Рассинхрон
AJAX_IDили список товаров не обёрнут в ожидаемый контейнер. - Кэш «залипает». Изменили свойства, а фильтр показывает старые значения — сбросьте кэш компонента и проверьте теги кэширования.
Итог
Вынос умного фильтра во включаемую область — это не «перенести код», а сохранить связку двух компонентов: одинаковый FILTER_NAME, тот же инфоблок и раздел, согласованные ЧПУ-правила и AJAX-идентификаторы, плюс живой фасетный индекс. Сделаете это аккуратно — получите переиспользуемый фильтр в любой части вёрстки без потери скорости и SEO.
Если каталог большой, вёрстка нестандартная, а фильтр нужен сразу в нескольких местах и на мобильных, мы в B2Bsite настраиваем такую связку под ключ — с фасетным индексом, корректным кэшем и рабочим AJAX. Поможем и с ускорением каталога, и с интеграцией цен и остатков из 1С, чтобы фильтр всегда отбирал по актуальным данным.
Частые вопросы
Почему фильтр во включаемой области ничего не фильтрует?
Скорее всего, у компонента фильтра и у списка товаров разные значения параметра FILTER_NAME. Они должны совпадать — обычно это arrFilter.
Можно ли вывести фильтр в общем шаблоне сайта?
Да, вызов catalog.smart.filter можно разместить в template.php или в области колонки. Главное, чтобы фильтр отработал раньше, чем список товаров прочитает переменную отбора.
Как определить текущий раздел внутри включаемой области?
Надёжнее всего передать SECTION_ID из основного компонента каталога через глобальную переменную. Альтернатива — разобрать ЧПУ и найти раздел по SECTION_CODE через CIBlockSection::GetList.
Нужен ли фасетный индекс, если фильтр вынесен отдельно?
Да, обязательно. Место вывода фильтра не влияет на его механику — скорость по-прежнему обеспечивает фасетный индекс, построенный в настройках инфоблока.
Почему после выноса фильтра перестал работать AJAX?
Обычно рассинхронизируются AJAX_ID фильтра и списка товаров, либо список не обёрнут в контейнер, который ожидает компонент. Приведите идентификаторы в соответствие.
Ломает ли вынос фильтра ЧПУ-адреса?
Нет, если параметры SEF_MODE и SEF_RULE в области совпадают с настройками комплексного компонента каталога. При расхождении правил адреса фильтра перестают формироваться корректно.
Как сбрасывать кэш вынесенного фильтра?
Кэш фильтра во включаемой области живёт отдельно от списка товаров. Используйте управляемое кэширование с тегами, чтобы он сбрасывался при изменении свойств и разделов.
Стоит ли хардкодить IBLOCK_ID в вызове фильтра?
Нет. На разных окружениях ID инфоблоков отличаются, и фильтр перестаёт показывать свойства. Получайте ID по символьному коду инфоблока или выносите в настройки.
Поможем с настройкой и поддержкой 1С-Битрикс: Управление сайтом
Поможем с настройкой, доработкой и поддержкой 1С-Битрикс: Управление сайтом.