Назад

Битрикс свой порядок в сортировке

Главная
Блог
Битрикс свой порядок в сортировке

При разработке проектов на Битрикс часто возникает необходимость отойти от стандартных вариантов сортировки элементов по 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 открывает широкие возможности для кастомизации вывода элементов в Битрикс:

  • Гибкость — полный контроль над последовательностью элементов

  • Совместимость — работает со стандартными компонентами Битрикс

  • Производительность — при правильном кешировании не создаёт избыточной нагрузки

Рекомендуемые сферы применения:

  • Интернет-магазины с приоритетными товарами

  • Лендинг-страницы с ручной сортировкой блоков

  • Интеграция с внешними системами управления контентом

  • Проекты со сложной бизнес-логикой отображения данных

Освоив этот метод, вы сможете решать сложные задачи сортировки, сохраняя при этом высокую производительность и используя стандартные механизмы платформы.

Нужен надежный исполнитель?
Разрабатываем сайты, выполняем миграцию на Битрикс, дорабатываем функционал, сопровождаем проекты, а также занимаемся поисковым продвижением и комплексным маркетингом
Получить консультацию
Читайте по теме
Все статьи
Нужен надежный исполнитель?
Разрабатываем сайты, выполняем миграцию на Битрикс, дорабатываем функционал, сопровождаем проекты, а также занимаемся поисковым продвижением и комплексным маркетингом
Получить консультацию
Все статьи