August 22, 2012

Bitrix:catalog.section - сортировка по двум параметрам

Всем привет! Сегодня я кратко расскажу о том как реализовать в стандартном компоненте сортировку одновременно по двум параметрам. Это бывает полезно в таких случаях когда например в каталоге уже настроена сортировка элементов (товаров) по какому то параметру, но какие то товары нужно вывести в начале списка или в конце (к примеру хиты продаж либо же какие то “непродаваемые товары” xD).

Стандартный компонент bitrix:catalog.secion сортировать сразу по двум параметрам не умеет, но зато это умеет делать функция CIBlockElement::GetList. Хм…

Тогда мы идем смотреть как реализован компонент каталога. Открываем /bitrix/components/bitrix/catalog.section/component.php и видим что это по сути обертка над уже знакомой нам функцией Getlist. Ну что ж, будем кастомизировать =) Стандартный компонент мы портить не будем т.к. в случае обновления движка все наши изменения затрутся. Поэтому мы копируем директорию catalog.section в /bitrix/components/bitrix/catalog.section.prop где уже будем делать необходимые правки.

Итак, сперва добавим необходимые поля для настройки сортировки в компоненте. Для этого открываем .parameters.php и добавляем туда такой код:

после:

<?php
//...

    "ELEMENT_SORT_FIELD" => array(
        "PARENT" => "DATA_SOURCE",
        "NAME" => GetMessage("IBLOCK_ELEMENT_SORT_FIELD"),
        "TYPE" => "LIST",
        "VALUES" => array(
            "shows" => GetMessage("IBLOCK_SORT_SHOWS"),
            "sort" => GetMessage("IBLOCK_SORT_SORT"),
            "timestamp_x" => GetMessage("IBLOCK_SORT_TIMESTAMP"),
            "name" => GetMessage("IBLOCK_SORT_NAME"),
            "id" => GetMessage("IBLOCK_SORT_ID"),
            "active_from" => GetMessage("IBLOCK_SORT_ACTIVE_FROM"),
            "active_to" => GetMessage("IBLOCK_SORT_ACTIVE_TO"),
        ),
        "ADDITIONAL_VALUES" => "Y",
        "DEFAULT" => "sort",
    ),
    "ELEMENT_SORT_ORDER" => array(
        "PARENT" => "DATA_SOURCE",
        "NAME" => GetMessage("IBLOCK_ELEMENT_SORT_ORDER"),
        "TYPE" => "LIST",
        "VALUES" => $arAscDesc,
        "DEFAULT" => "asc",
        "ADDITIONAL_VALUES" => "Y",
    ),

добавляем

<?php
//...

    "ELEMENT_SORT_FIELD2" => array(
        "PARENT" => "DATA_SOURCE",
        "NAME" => GetMessage("IBLOCK_ELEMENT_SORT_FIELD")."-2",
        "TYPE" => "LIST",
        "VALUES" => array(
            "shows" => GetMessage("IBLOCK_SORT_SHOWS"),
            "sort" => GetMessage("IBLOCK_SORT_SORT"),
            "timestamp_x" => GetMessage("IBLOCK_SORT_TIMESTAMP"),
            "name" => GetMessage("IBLOCK_SORT_NAME"),
            "id" => GetMessage("IBLOCK_SORT_ID"),
            "active_from" => GetMessage("IBLOCK_SORT_ACTIVE_FROM"),
            "active_to" => GetMessage("IBLOCK_SORT_ACTIVE_TO"),
        ),
        "ADDITIONAL_VALUES" => "Y",
        "DEFAULT" => "sort",
    ),
    "ELEMENT_SORT_ORDER2" => array(
        "PARENT" => "DATA_SOURCE",
        "NAME" => GetMessage("IBLOCK_ELEMENT_SORT_ORDER")."-2",
        "TYPE" => "LIST",
        "VALUES" => $arAscDesc,
        "DEFAULT" => "asc",
        "ADDITIONAL_VALUES" => "Y",
    ),

Можно было бы вместо копирования конечно добавить “MULTIPLE” => “Y” к этим полям и дописывать обработку массивов с настройками для сортировки, но зачем нам лишние телодвижения если нужно всего лишь добавить еще одну сортировку =)

Теперь идем в component.php:

после:

<?php
//...

if(strlen($arParams["ELEMENT_SORT_FIELD"])<=0) {
    $arParams["ELEMENT_SORT_FIELD"]="sort";
}

if(!preg_match('/^(asc|desc|nulls)(,asc|,desc|,nulls){0,1}$/i', $arParams["ELEMENT_SORT_ORDER"])) {
    $arParams["ELEMENT_SORT_ORDER"]="asc";
}

добавляем

<?php
//...

if(strlen($arParams["ELEMENT_SORT_FIELD2"])<=0) {
    $arParams["ELEMENT_SORT_FIELD2"]="sort";
}

if(!preg_match('/^(asc|desc|nulls)(,asc|,desc|,nulls){0,1}$/i', $arParams["ELEMENT_SORT_ORDER2"])) {
    $arParams["ELEMENT_SORT_ORDER2"]="asc";
}

и добавляем новые переменные в массив для сортировки:

<?php
//...

$arSort = array(
    $arParams["ELEMENT_SORT_FIELD"] => $arParams["ELEMENT_SORT_ORDER"],
    //Добавляем еще одну строчку
    $arParams["ELEMENT_SORT_FIELD2"] => $arParams["ELEMENT_SORT_ORDER2"],
    "ID" => "DESC",
);

Теперь все сохраняем и в местах где нужен компонент каталога с двумя полями для сортировки просто вызываем bitrix:catalog.section.prop вместо bitrix:catalog.section

В его настройках мы видим:

bitrix.catalog.section.prop

Вот собственно и все! Удачи!