Стоит следующая задача: отсортировать элементы, полученные в стандартном компоненте bitrix:catalog по полю IBLOCK_SECTION_ID.
Как оказалось, штатной такой возможности нет, в методе CAllIBlockElement::PrepareGetList() не предусмотрено соответствующего правила.
[spoiler]
Казалось бы, обычная задача: имеем N разделов, M подразделов, вручную установлена сортировка от 10 до 100 у элементов, у схожих в рамках одного подраздела элементов сортировка одинаковая.
При заходе на страницу подраздела всё работает как надо - сначала идут элементы с SORT 10, затем 20 и т.д.
Однако если зайти на страницу родительского раздела, то элементы сортируются следующим образом:
из ВСЕХ подразделов выбираются элементы с SORT 10, затем 20 и т.д.
А нужно - чтобы сначала из одного подраздела SORT-10,20,30..., затем из второго и так до конца.
Если мы в CAllIBlockElement::PrepareGetList() добавим нужное правило, такая логика станет возможной. Но, как известно, модифицировать ядро нехорошо.
Поэтому идея:
в файле /bitrix/modules/iblock/classes/general/iblockelement.php
в методе CAllIBlockElement::PrepareGetList() начиная со строки 2589 по строку 2609 идет следующий код, в котором на наш взгляд не хватает последней выделенной строчки
if($by == "ID") $arSqlOrder[$by] = CIBlock::_Order("BE.ID", $order, "desc", false);
elseif($by == "NAME") $arSqlOrder[$by] = CIBlock::_Order("BE.NAME", $order, "desc", false);
elseif($by == "STATUS") $arSqlOrder[$by] = CIBlock::_Order("BE.WF_STATUS_ID", $order, "desc");
elseif($by == "XML_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.XML_ID", $order, "desc");
elseif($by == "CODE") $arSqlOrder[$by] = CIBlock::_Order("BE.CODE", $order, "desc");
elseif($by == "TAGS") $arSqlOrder[$by] = CIBlock::_Order("BE.TAGS", $order, "desc");
elseif($by == "TIMESTAMP_X") $arSqlOrder[$by] = CIBlock::_Order("BE.TIMESTAMP_X", $order, "desc");
elseif($by == "CREATED") $arSqlOrder[$by] = CIBlock::_Order("BE.DATE_CREATE", $order, "desc");
elseif($by == "CREATED_DATE") $arSqlOrder[$by] = CIBlock::_Order($DB->DateFormatToDB("YYYY.MM.DD", "BE.DATE_CREATE"), $order, "desc");
elseif($by == "IBLOCK_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.IBLOCK_ID", $order, "desc");
elseif($by == "MODIFIED_BY") $arSqlOrder[$by] = CIBlock::_Order("BE.MODIFIED_BY", $order, "desc");
elseif($by == "ACTIVE") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE", $order, "desc");
elseif($by == "ACTIVE_FROM") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE_FROM", $order, "desc");
elseif($by == "ACTIVE_TO") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE_TO", $order, "desc");
elseif($by == "SORT") $arSqlOrder[$by] = CIBlock::_Order("BE.SORT", $order, "desc");
elseif($by == "SHOW_COUNTER") $arSqlOrder[$by] = CIBlock::_Order("BE.SHOW_COUNTER", $order, "desc");
elseif($by == "SHOW_COUNTER_START") $arSqlOrder[$by] = CIBlock::_Order("BE.SHOW_COUNTER_START", $order, "desc");
elseif($by == "RAND") $arSqlOrder[$by] = CIBlockElement::GetRandFunction(true);
elseif($by == "SHOWS") $arSqlOrder[$by] = CIBlock::_Order(CIBlockElement::GetShowedFunction(), $order, "desc", false);
elseif($by == "HAS_PREVIEW_PICTURE") $arSqlOrder[$by] = CIBlock::_Order(CIBlock::_NotEmpty("BE.PREVIEW_PICTURE"), $order, "desc", false);
elseif($by == "HAS_DETAIL_PICTURE") $arSqlOrder[$by] = CIBlock::_Order(CIBlock::_NotEmpty("BE.DETAIL_PICTURE"), $order, "desc", false);
>>>>>>>>>>>>>>>>>>>>>>>>>
elseif($by == "SECTION_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.IBLOCK_SECTION_ID", $order, "desc", false);
<<<<<<<<<<<<<<<<<<<<<<<<<
|
В таблице b_iblock_elements присутствует поле IBLOCK_SECTION_ID, непонятно почему про это забыли в данном методе.