При разработке проектов на Битрикс часто возникает необходимость отойти от стандартных вариантов сортировки элементов по ID, дате или названию. Типичные сценарии:
-
Товары в порядке разделов — когда последовательность товаров должна соответствовать сортировке категорий каталога
-
Ручная расстановка приоритетов — например, сначала акционные товары, затем новинки, после чего хиты продаж
-
Внешняя логика排序 — интеграция с CRM, ERP-системами или алгоритмическое определение порядка
До выхода версии Битрикс 18.6.700 разработчикам приходилось использовать обходные решения, но теперь появилась элегантная встроенная возможность — сортировка по массиву ID.
Основной принцип решения
Начиная с версии 18.6.700, Битрикс позволяет передавать в параметр сортировки не только ключевые слова asc/desc, но и массив идентификаторов в нужной последовательности.
Базовый синтаксис
// Задаём желаемую последовательность ID элементов
$customOrder = [5, 3, 1, 2, 4];
// Используем в параметрах сортировки
$arOrder = ['ID' => $customOrder];
// Обязательно указываем тот же массив в фильтре
$arFilter = ['ID' => $customOrder];Важное замечание: без указания фильтра по этим ID элементы, отсутствующие в массиве, также попадут в выборку, но в конце списка.
Практический пример: сортировка товаров по разделам
Рассмотрим реальный кейс интернет-магазина, где товары должны выводиться в соответствии с порядком разделов каталога.
Шаг 1: Получаем разделы с учётом их сортировки
// Настройки инфоблока
$IBLOCK_ID = 5; // ID вашего инфоблока
// Получаем разделы, отсортированные по полю SORT
$arSections = [];
$res = CIBlockSection::GetList(
["SORT" => "ASC"], // Сортировка разделов
[
"IBLOCK_ID" => $IBLOCK_ID,
"ACTIVE" => "Y"
],
false,
["ID", "NAME"] // Выбираем только необходимые поля
);
while ($arSection = $res->GetNext()) {
$arSections[] = [
'ID' => $arSection['ID'],
'NAME' => $arSection['NAME']
];
}Шаг 2: Формируем последовательность товаров
$arSortedProductIds = [];
// Для каждого раздела получаем его товары
foreach ($arSections as $arSection) {
$resProducts = CIBlockElement::GetList(
["SORT" => "ASC"], // Сортировка товаров внутри раздела
[
"IBLOCK_ID" => $IBLOCK_ID,
"ACTIVE" => "Y",
"SECTION_ID" => $arSection['ID'],
"INCLUDE_SUBSECTIONS" => "Y" // Включаем подразделы
],
false,
false,
["ID", "NAME"]
);
while ($arProduct = $resProducts->GetNext()) {
// Избегаем дублирования ID
if (!in_array($arProduct['ID'], $arSortedProductIds)) {
$arSortedProductIds[] = $arProduct['ID'];
}
}
}
// Теперь $arSortedProductIds содержит ID товаров в нужном порядкеШаг 3: Интеграция со стандартным компонентом
// В result_modifier.php или в параметрах компонента
$APPLICATION->IncludeComponent(
"bitrix:catalog.section",
"template_name",
[
"IBLOCK_ID" => $IBLOCK_ID,
"ELEMENT_SORT_FIELD" => "ID",
"ELEMENT_SORT_ORDER" => $arSortedProductIds, // Наш кастомный порядок
"FILTER_NAME" => "arrFilter", // Обязательный параметр!
"SET_TITLE" => "Y",
// Другие параметры компонента...
]
);Оптимизация производительности и кеширование
Поскольку формирование кастомной сортировки требует множества запросов к базе данных, критически важно реализовать эффективное кеширование.
Вариант 1: Использование встроенного кеша Битрикс
// Настройки кеширования
$cache = Bitrix\Main\Data\Cache::createInstance();
$cacheId = 'custom_product_sort_' . $IBLOCK_ID . '_' . SITE_ID;
$cacheDir = '/custom_sort/';
$cacheTime = 86400; // 24 часа
if ($cache->initCache($cacheTime, $cacheId, $cacheDir)) {
$arSortedProductIds = $cache->getVars();
} elseif ($cache->startDataCache()) {
// Защита от одновременного генерирования кеша
Bitrix\Main\Application::getConnection()->lock($cacheId);
try {
// Генерируем массив сортировки (как в примере выше)
$arSortedProductIds = generateCustomSort($IBLOCK_ID);
$cache->endDataCache($arSortedProductIds);
Bitrix\Main\Application::getConnection()->unlock($cacheId);
} catch (Exception $e) {
$cache->abortDataCache();
Bitrix\Main\Application::getConnection()->unlock($cacheId);
}
}Вариант 2: Фоновая генерация через агентов
Для редко меняющихся данных оптимально использовать агентов или cron-задачи:
// Функция для агента
function updateCustomSort() {
$IBLOCK_ID = 5;
$arSortedProductIds = generateCustomSort($IBLOCK_ID);
// Сохраняем в файл для быстрого доступа
$filePath = $_SERVER['DOCUMENT_ROOT'] . '/upload/custom_sort_' . $IBLOCK_ID . '.json';
file_put_contents($filePath, json_encode($arSortedProductIds));
return "updateCustomSort();"; // Перезапускаем агент
}
// В нужном месте загружаем данные
$filePath = $_SERVER['DOCUMENT_ROOT'] . '/upload/custom_sort_' . $IBLOCK_ID . '.json';
if (file_exists($filePath)) {
$arSortedProductIds = json_decode(file_get_contents($filePath), true);
} else {
// Если файла нет, генерируем на лету
$arSortedProductIds = generateCustomSort($IBLOCK_ID);
}Дополнительные улучшения и обработка крайних случаев
Проверка актуальности ID элементов
Со временем некоторые товары могут быть удалены или деактивированы. Рекомендуется фильтровать массив:
function validateProductIds($productIds, $IBLOCK_ID) {
$existingIds = [];
$res = CIBlockElement::GetList(
[],
[
"IBLOCK_ID" => $IBLOCK_ID,
"ID" => $productIds,
"ACTIVE" => "Y"
],
false,
false,
["ID"]
);
while ($arItem = $res->Fetch()) {
$existingIds[] = $arItem['ID'];
}
// Сохраняем оригинальный порядок, но только для существующих элементов
return array_intersect($productIds, $existingIds);
}
// Использование
$arSortedProductIds = validateProductIds($arSortedProductIds, $IBLOCK_ID);Альтернативный подход: сортировка по пользовательскому свойству
Если порядок элементов относительно статичен, можно использовать пользовательское свойство:
// Создаём свойство "SORT_ORDER" типа "Число"
$arOrder = [
"PROPERTY_SORT_ORDER" => "ASC",
"SORT" => "ASC",
"ID" => "ASC"
];Этот подход проще в реализации, но менее гибкий при частых изменениях порядка.
Заключение и рекомендации
Представленная техника сортировки по массиву ID открывает широкие возможности для кастомизации вывода элементов в Битрикс:
-
Гибкость — полный контроль над последовательностью элементов
-
Совместимость — работает со стандартными компонентами Битрикс
-
Производительность — при правильном кешировании не создаёт избыточной нагрузки
Рекомендуемые сферы применения:
-
Интернет-магазины с приоритетными товарами
-
Лендинг-страницы с ручной сортировкой блоков
-
Интеграция с внешними системами управления контентом
-
Проекты со сложной бизнес-логикой отображения данных
Освоив этот метод, вы сможете решать сложные задачи сортировки, сохраняя при этом высокую производительность и используя стандартные механизмы платформы.