Сегодня довелось мне полдня ковыряться со сложной сортировкой. Сложность ее заключается в том, что выводятся данные из одного инфоблока, а сортировать надо по данным из другого инфоблока. Решение нашлось не сразу.[spoiler]
Сразу покажу результат:

Тоже самое вживую в действии:
Теперь немного расскажу, как это делалось. Перед нами таблица товарного раздела, где выводится в общем-то в простом виде товары, их характеристики, цены. В данном случае - это жесткие диски. Понятное дело, что жесткие диски - это такой товар, внешний вид которого имеет низкое значение, поэтому такого рода товары лучше всего выводить в формате таблицы (прайс-лист). Но у таких товаров крайне важны их характеристики, поэтому желательно их показывать в этой таблице и сортировать по ним. Вся загвоздка в том, что товары - это отдельный инфоблок, в нем хранятся собственно структура торгового каталога, названия, служебные параметры товаров, цены и т.д. А все характеристики хранятся в других инфоблоках, элементы которых взаимосвязаны. Характеристики жестких дисков - это один инфоблок, характеристики ноутбуков - это другой инфоблок и т.д. Чтобы было более понятно я приведу еще скриншот админки:

Сортировка хитрая нужна, обычные методы сортировки тут не прокатят. Итак, для начала делаем выборку всех элементов товарного каталога для данного раздела, к нему же применяем постраничную навигацию, но выбираем только ID.
Создаем массив всех ID товаров, доступных на данном уровне. Затем выбираем записи из инфоблока описаний, которые привязаны ко всем ID товаров и сортируем их по нужному параметру. Здесь опять же применяем те же самые параметры навигации. Но выбираем мы только признак привязки к товарному каталогу. В моем случае для привязки характеристик к товарному каталогу используется поле мнемонического кода. Так как инфоблоки с характеристиками в чистом виде не выводятся, код там ни к чему, можно его смело использовать.
Ну а дальше всё просто, делаем выборку из товарного инфоблока с ID полученными при выборке из инфоблока характеристик. Параметры навигации тут уже не применимы, так как объем выборки будет равен объему первой страницы. Далее нам остается "склеить" сортированный массив с новой выборкой товарных предложений и получим нужный результат.
Производительность данного компонента вполне обычная. К тому же такое представление на треть быстрее по времени и на треть меньше запросов требует, чем полное представление подобного каталога:

Сразу покажу результат:

Тоже самое вживую в действии:
Теперь немного расскажу, как это делалось. Перед нами таблица товарного раздела, где выводится в общем-то в простом виде товары, их характеристики, цены. В данном случае - это жесткие диски. Понятное дело, что жесткие диски - это такой товар, внешний вид которого имеет низкое значение, поэтому такого рода товары лучше всего выводить в формате таблицы (прайс-лист). Но у таких товаров крайне важны их характеристики, поэтому желательно их показывать в этой таблице и сортировать по ним. Вся загвоздка в том, что товары - это отдельный инфоблок, в нем хранятся собственно структура торгового каталога, названия, служебные параметры товаров, цены и т.д. А все характеристики хранятся в других инфоблоках, элементы которых взаимосвязаны. Характеристики жестких дисков - это один инфоблок, характеристики ноутбуков - это другой инфоблок и т.д. Чтобы было более понятно я приведу еще скриншот админки:

Сортировка хитрая нужна, обычные методы сортировки тут не прокатят. Итак, для начала делаем выборку всех элементов товарного каталога для данного раздела, к нему же применяем постраничную навигацию, но выбираем только ID.
$rsElementsAll = CIBlockElement::GetList(false, $arFilter, false, false, array('ID'));
while ($arEl = $rsElementsAll->GetNext()) $allIDs[] = $arEl['ID']; |
Создаем массив всех ID товаров, доступных на данном уровне. Затем выбираем записи из инфоблока описаний, которые привязаны ко всем ID товаров и сортируем их по нужному параметру. Здесь опять же применяем те же самые параметры навигации. Но выбираем мы только признак привязки к товарному каталогу. В моем случае для привязки характеристик к товарному каталогу используется поле мнемонического кода. Так как инфоблоки с характеристиками в чистом виде не выводятся, код там ни к чему, можно его смело использовать.
// $_SESSION['sorting_prop'] - код свойства по которому сортируем
// $_SESSION['sorting_prop_dir'] - направление сортировки ASC | DESC
// $arResult['SECTION']['UF_DESCRIPTIONS'] - ID инфоблока с характеристиками для данного раздела
$rsSortedDescr = CIblockElement::GetList(
array("PROPERTY_".$_SESSION['sorting_prop']=>$_SESSION['sorting_prop_dir']),
array('CODE'=>$allIDs, 'IBLOCK_ID'=>$arResult['SECTION']['UF_DESCRIPTIONS'], 'ACTIVE'=>"Y"),
false, $arNavParams, array("CODE")
);
$arSortedDescriptions = array();
while ($arSortedDescr = $rsSortedDescr->GetNext()) {
if ($arSortedDescr['CODE']) {
$arSortedDescriptions[] = $arSortedDescr['CODE'];
}
}
$arFilter['ID'] = $arSortedDescriptions; |
Ну а дальше всё просто, делаем выборку из товарного инфоблока с ID полученными при выборке из инфоблока характеристик. Параметры навигации тут уже не применимы, так как объем выборки будет равен объему первой страницы. Далее нам остается "склеить" сортированный массив с новой выборкой товарных предложений и получим нужный результат.
// $arResult['ITEMS'] - результат выборки товаров по фильтру
if ($arSortedDescriptions) {
$old_items = $arResult['ITEMS'];
$arResult['ITEMS'] = array();
foreach ($arSortedDescriptions as $item_id) {
if (is_array($old_items[$item_id])) {
$arResult['ITEMS'][$item_id] = $old_items[$item_id];
}
}
} |
Производительность данного компонента вполне обычная. К тому же такое представление на треть быстрее по времени и на треть меньше запросов требует, чем полное представление подобного каталога:
