Очень часто на странице нужно разместить несколько компонентов, которые должны работать вместе.
Самый яркий пример — страница каталога, где есть компонент «Умный фильтр» и компонент «Список товаров».
Как сделать так, чтобы изменения в фильтре приводили к перезагрузке списка товаров?
Способ 1: Классический (через GET-параметры и глобальную переменную)
Это самый простой, надежный и фундаментальный способ, который используется в стандартных компонентах каталога.
Поняв его, вы поймете всю логику взаимодействия.
Как это работает (правильная схема):
- Страница (Оркестратор): На странице, где размещаются компоненты, вы объявляете имя глобальной переменной (например, $arrFilter), которая будет служить «шиной данных». Вы передаете это имя обоим компонентам через параметр FILTER_NAME.
- Компонент Фильтра (Активный участник): Этот компонент при своей работе проверяет $_GET. Если он находит там данные из своей формы, он формирует из них массив фильтрации и добавляет (мержит) его в глобальную переменную, имя которой он получил в FILTER_NAME.
- Компонент Списка (Пассивный участник): Этот компонент выполняется после компонента фильтра. Он ничего не знает про $_GET. Его задача — просто взять уже готовую глобальную переменную (имя которой он также получил в FILTER_NAME) и использовать ее в своем вызове CIBlockElement::GetList.
Пример реализации:
1. Код на странице (/catalog/index.php):
<?
// 1. Задаем имя для нашего "канала" связи.
$filterName = "myCatalogFilter";
// 2. Можно задать базовые, обязательные условия фильтрации.
$GLOBALS[$filterName] = ["ACTIVE" => "Y"];
// 3. Вызываем компонент ФИЛЬТРА.
// Он проанализирует URL и, если нужно, дополнит $GLOBALS[$filterName].
$APPLICATION->IncludeComponent(
"my:filter",
".default",
[
"FILTER_NAME" => $filterName, // Говорим фильтру, с какой переменной работать
]
);
// 4. Вызываем компонент СПИСКА.
// Он просто возьмет уже полностью готовую переменную $GLOBALS[$filterName].
$APPLICATION->IncludeComponent(
"my:catalog.list",
".default",
[
"FILTER_NAME" => $filterName, // Говорим списку, откуда брать фильтр
"IBLOCK_ID" => 5, // Другие параметры
]
);
?>
2. Логика компонента Фильтра (my:filter/component.php)
<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
$filterName = $arParams['FILTER_NAME'] ?? 'arrFilter';
// Убедимся, что глобальная переменная существует
if (!isset($GLOBALS[$filterName]) || !is_array($GLOBALS[$filterName])) {
$GLOBALS[$filterName] = [];
}
// Проверяем, есть ли в GET-запросе данные из нашей формы (например, поле "price_from")
if (isset($_GET['price_from']) && (int)$_GET['price_from'] > 0) {
// Формируем массив фильтра НА ОСНОВЕ GET
$userFilter = [
'>=PROPERTY_PRICE' => (int)$_GET['price_from']
];
// !!! КЛЮЧЕВОЙ МОМЕНТ: ОБЪЕДИНЯЕМ наш фильтр с тем, что уже было в глобальной переменной
$GLOBALS[$filterName] = array_merge($GLOBALS[$filterName], $userFilter);
}
// ... здесь обработка других полей фильтра ...
// Просто подключаем шаблон формы
$this->includeComponentTemplate();
3. Логика компонента Списка (my:catalog.list/component.php)
<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
$filterName = $arParams['FILTER_NAME'] ?? 'arrFilter';
// Просто берем готовую глобальную переменную. Никакого анализа $_GET!
$arFilter = $GLOBALS[$filterName];
if (!is_array($arFilter)) {
$arFilter = [];
}
// Добавляем свои обязательные условия
$arFilter['IBLOCK_ID'] = $arParams['IBLOCK_ID'];
$arFilter['ACTIVE_DATE'] = 'Y';
// Выполняем выборку с готовым, объединенным фильтром
$rsElements = CIBlockElement::GetList([], $arFilter);
// ... дальнейшая логика ...
Способ 2: Современный (через AJAX)
Этот способ не требует перезагрузки страницы и используется в современных шаблонах.
Как работает:
- Компонент Фильтра: При изменении любого поля он с помощью JavaScript собирает все значения.
- JavaScript: Формирует AJAX-запрос к странице, передавая в него параметры фильтра и специальный параметр bxajaxid, который указывает, какой именно компонент нужно перезагрузить.
- Сервер (Битрикс): Получает запрос, видит bxajaxid компонента-списка, выполняет только его с новыми параметрами и возвращает только его HTML.
- JavaScript: Получает HTML и заменяет им содержимое контейнера компонента-списка.
Этот механизм включается параметром «AJAX_MODE» => «Y» у компонента-списка, а стандартный компонент catalog.smart.filter уже умеет с ним работать.
Способ 3: Внутри комплексного компонента
Это самый правильный архитектурный подход. Фильтр и список являются частями одного комплексного компонента.
Как работает:
Логика идентична Способу 1, но вся «оркестрация» происходит не на странице, а внутри шаблона комплексного компонента.
- Вызывается шаблон комплексного компонента.
- Внутри него сначала вызывается IncludeComponent для фильтра.
- Фильтр, как и раньше, модифицирует глобальную переменную.
- Сразу после этого вызывается IncludeComponent для списка.
- Список подхватывает уже измененную глобальную переменную.
Поскольку все происходит в рамках одного PHP-хита, все работает идеально.
Вывод:
Способ взаимодействия компонентов зависит от задачи.
Для простых страниц достаточно классического GET-метода с глобальной переменной.
Для современных, «живых» интерфейсов — встроенный механизм AJAX_MODE.
А для построения больших, логически связанных разделов сайта, таких как каталог, всегда используйте комплексный компонент, который инкапсулирует всю логику взаимодействия внутри себя.
Главное — помнить правильное распределение ролей: фильтр — активный, список — пассивный.
взаимодействие компонентов, Битрикс, умный фильтр, AJAX, GET-параметры, composite, комплексный компонент.