Задача - сделать разумные настройки для сортировки элементов инфоблока в компонентах с выборками. [spoiler]
Нормальные настройки сортировки обладают некоторыми особенностями. Во-первых, сортировать можно по нескольким полям в разных направлениях. Во-вторых, сортировать можно по свойствам элементов.
Я уже забыл, как выглядят системные компоненты битрикса, но на сколько я помню там предлагается сортировка по одному-двум полям, а сортировка по свойствам предлагается путем ввода кода свойства в дополнительное поле. Неудобно, в общем.
Итак, исправляем первое неудобство. Если мы знаем инфоблок, откуда выбираются данные, значит мы можем определить все свойства инфоблока, по которым возможна сортировка. Делается это так:
В этом куске кода мы просто определили возможные варианты значений для направления и поля сортировки. Собственно сами параметры мы задаем ниже.
Алгоритм всего описанного выше простой: показываем пользователю пару параметров для сортировки "поле-направление". Если пользователь определяет эту пару, то подгружаем еще одну такую пару (без значения). Если он вторую пару указывает, то подгружаем еще и так до бесконечности, пока поля не кончатся. В итоге в параметрах компонента мы будем иметь несколько значений SORT_FIELD_Х, где Х - порядковый номер пары сортировки. Форма редактирования настроек компонента теперь будет выглядеть так:
Разобрать в компоненте набор таких параметров не составит труда. Вот пример моей разборки:
Что касается практического применения, то мне приходится достаточно часто устанавливать сортировку по 3-5 разным параметрам, например сортировка товаров в разделе: SORT, избранность, популярность, пользовательский рейтинг, ID.
Небольшое замечание. Имеет смысл предлагать сортировку только по свойствам типа текст (S), число (N), значение списка (L). По остальным типам свойств сортировка не имеет смысла, так как значением будут идентификаторами файлов, других элементов и еще не бог весть чего.
Нормальные настройки сортировки обладают некоторыми особенностями. Во-первых, сортировать можно по нескольким полям в разных направлениях. Во-вторых, сортировать можно по свойствам элементов.
Я уже забыл, как выглядят системные компоненты битрикса, но на сколько я помню там предлагается сортировка по одному-двум полям, а сортировка по свойствам предлагается путем ввода кода свойства в дополнительное поле. Неудобно, в общем.
Итак, исправляем первое неудобство. Если мы знаем инфоблок, откуда выбираются данные, значит мы можем определить все свойства инфоблока, по которым возможна сортировка. Делается это так:
$arSortingDir = array( 'ASC' => "По возрастанию", 'DESC' => "По убыванию" ); $arSortingFields = array( "id" => "ID", "timestamp_x" => "Последнее изменение", "name" => "Название", "active_from" => "Дата начала активности", "active_to" => "Дата окончания активности", "show_counter_start" => "Время первого показа элемента", "shows" => "Усредненное количество показов", "rand" => "Случайным образом", ); // Список свойств инфоблока, по которым мы тоже можем сортировать if ($arCurrentValues["IBLOCK_ID"] > 0) { $rsProps = CIBlockProperty::GetList(array("NAME"=>"ASC"), array("IBLOCK_ID"=>$arCurrentValues["IBLOCK_ID"])); // Сортируем по всем доступным полям while ($arProp = $rsProps->GetNext()) { $arSortingFields['property_'.$arProp['ID']] = "Свойство: ".$arProp['NAME']; } } |
В этом куске кода мы просто определили возможные варианты значений для направления и поля сортировки. Собственно сами параметры мы задаем ниже.
// Перебираем все текущие значения и показываем в форме редактирования компонента + 1 пустое поле для новой сортировки if (empty($arCurrentValues['SORT_FIELD_1'])) $arCurrentValues['SORT_FIELD_1'] = "id"; $count = 1; do { if ($count == 2) { $arSortingFields = array_merge(array(""=>"Не использовать"), $arSortingFields); } $arComponentParameters['PARAMETERS']["SORT_FIELD_".$count] = array( "PARENT" => "SORTING", "NAME" => "Поле для сортировки ".$count, "TYPE" => "LIST", "MULTIPLE" => "N", "ADDITIONAL_VALUES" => "N", "VALUES" => $arSortingFields, "REFRESH" => "Y", ); if ($count == 1) { $arComponentParameters['PARAMETERS']["SORT_FIELD_".$count]['DEFAULT'] = "id"; } $arComponentParameters['PARAMETERS']["SORT_DIR_".$count] = array( "PARENT" => "SORTING", "NAME" => "Направление сортировки ".$count, "TYPE" => "LIST", "MULTIPLE" => "N", "DEFAULT" => "ASC", "ADDITIONAL_VALUES" => "N", "VALUES" => $arSortingDir, "REFRESH" => "N", ); $count++; } while (strlen($arCurrentValues['SORT_FIELD_'.($count-1)])); // всегда будет показывать первое поле сортировки + 1 пустое |
Алгоритм всего описанного выше простой: показываем пользователю пару параметров для сортировки "поле-направление". Если пользователь определяет эту пару, то подгружаем еще одну такую пару (без значения). Если он вторую пару указывает, то подгружаем еще и так до бесконечности, пока поля не кончатся. В итоге в параметрах компонента мы будем иметь несколько значений SORT_FIELD_Х, где Х - порядковый номер пары сортировки. Форма редактирования настроек компонента теперь будет выглядеть так:
Разобрать в компоненте набор таких параметров не составит труда. Вот пример моей разборки:
// Дефолтная сортировка $arSorting = array( 'shows'=>"DESC", 'property__score'=>"DESC", 'property__featured'=>"DESC" ); // Сортировка из параметров if ($arParams['SORT_FIELD_1'] AND $arParams['SORT_DIR_1']) { $arSorting = array(); foreach ($arParams as $param_k => $param_v) { $dir = strtoupper($arParams['SORT_DIR_'.intval(str_replace("SORT_FIELD_", "", $param_k))]); if (strpos($param_k, "SORT_FIELD_") === 0 AND strlen($param_v) AND in_array($dir, array("DESC", "ASC"))) { // проверяем корректность ключа и направления сортировки $arSorting[$param_v] = $dir; } } } |
Что касается практического применения, то мне приходится достаточно часто устанавливать сортировку по 3-5 разным параметрам, например сортировка товаров в разделе: SORT, избранность, популярность, пользовательский рейтинг, ID.
Небольшое замечание. Имеет смысл предлагать сортировку только по свойствам типа текст (S), число (N), значение списка (L). По остальным типам свойств сортировка не имеет смысла, так как значением будут идентификаторами файлов, других элементов и еще не бог весть чего.