Сортировка по цене каталога в поиске

Стандартный шаблон компонента поиска "Битрикса" представляет собой аккуратный, но не совсем подходящий интернет-магазину список результатов (кстати, hint: в последних версиях "Битрикса" появился красивый компонент поиска по каталогу - bitrix:catalog.search, который можно поставить на страница поиска - /search/index.php и это отчасти решит проблему).

Большинство наших клиентов просят переделать шаблон страницы поиска таким образом, чтобы он соответствовал шаблону каталога. При этом не составляет большого труда переделать сам вывод - легко получить все поля элемента каталога по ITEM_ID каждого элемента выходного массива поиска ($arResult['ITEMS'] и исправить шаблон в соответствии с шаблоном витрины (раздела каталога). Проблемы возникают, когда просят при этом реализовать также сортировку (например, по цене) и "умный" фильтр. Про фильтр - отдельная история, здесь же опишу простой подход, который позволяет выводить результаты поиска в нужном нам порядке, т.е. с правильной сортировкой.
[spoiler]
Идея

Есть событие BeforeIndex, к которому можно привязать обработчик и в нем задавать необходимый вес поиска (CUSTOM_RANK) любому элементу каталога. Напишем функцию, которая будет вычислять CUSTOM_RANK в зависимости от наличия (от большего к меньшему, т.е. сначала идут товары, которых больше всего на складе) и в зависимости от цены (от меньшего к большему, т.е. дешевые товары идут первыми).

Реализация

В файле init.php добавим обработчик, который вызывается перед индексацией элемента каталога:
AddEventHandler("search", "BeforeIndex", "BeforeIndexHandler");
function BeforeIndexHandler($arFields) {
   if($arFields["MODULE_ID"] == "iblock" && $arFields["ITEM_ID"]) {
      CModule::IncludeModule('catalog');
      $arProduct = CCatalogProduct::GetByID($arFields["ITEM_ID"]);
      if($arProduct['QUANTITY'] <= 0)
         $k = 1;
      else
         $k = $arProduct['QUANTITY'] * 100;
      $dbPrice = CPrice::GetList(array(),array("PRODUCT_ID" => $arFields["ITEM_ID"],"CATALOG_GROUP_ID" => 2));
      $arPrice = $dbPrice->Fetch();
      
      $arFields['CUSTOM_RANK'] = $k * round(10000000/$arPrice['PRICE']);
   }
   return $arFields;
} 
Для товаров без остатка ($arProduct['QUANTITY'] <= 0) - задаем коэффициент веса = 1; для товаров на складе - кратно остатку на складе (в примере умножаем остаток на 100, но можно выбрать любое другое число, в зависимости от того, что важнее - выводить первыми товары с бОльшим остатком, или выводить более дешевые товары, но с меньшим остатком).

Итоговый вес для индексации - задаем прямо пропорциональным полученному коэффициенту и обратно пропорциональным цене товара.
Страницы: 1  2  
0
16.01.2025 19:12:33
0
16.01.2025 19:22:14
0
16.01.2025 19:22:24
0
16.01.2025 19:22:28
0
16.01.2025 19:22:36
0
16.01.2025 19:22:37
0
16.01.2025 19:22:46
0
16.01.2025 19:22:47
0
16.01.2025 19:22:48
-1 OR 2+398-398-1=0+0+0+1 --
0
16.01.2025 19:22:48
-1 OR 3+398-398-1=0+0+0+1 --
0
16.01.2025 19:22:48
-1 OR 2+443-443-1=0+0+0+1
0
16.01.2025 19:22:49
-1 OR 3+443-443-1=0+0+0+1
0
16.01.2025 19:22:49
-1' OR 2+765-765-1=0+0+0+1 --
0
16.01.2025 19:22:49
-1' OR 3+765-765-1=0+0+0+1 --
0
16.01.2025 19:22:50
-1' OR 2+103-103-1=0+0+0+1 or 'szpQEgmB'='
0
16.01.2025 19:22:50
-1' OR 3+103-103-1=0+0+0+1 or 'szpQEgmB'='
0
16.01.2025 19:22:51
-1" OR 2+538-538-1=0+0+0+1 --
0
16.01.2025 19:22:52
-1" OR 3+538-538-1=0+0+0+1 --
0
16.01.2025 19:23:00
0
16.01.2025 19:23:05
1*if(now()=sysdate(),sleep(15),0)
0
16.01.2025 19:23:12
0
16.01.2025 19:23:23
10'XOR(1*if(now()=sysdate(),sleep(15),0))XOR'Z
0
16.01.2025 19:23:29
0
16.01.2025 19:23:35
10"XOR(1*if(now()=sysdate(),sleep(15),0))XOR"Z
0
16.01.2025 19:23:43
0
16.01.2025 19:23:48
(sel ect(0)from(select(sleep(15)))v)/*'+(select(0)fr om(sel ect(sleep(15)))v)+'"+(select(0)fr om(select(sleep(15)))v)+"*/
0
16.01.2025 19:23:54
0
16.01.2025 19:23:58
1-1; waitfor delay '0:0:15' --
0
16.01.2025 19:24:05

Страницы: 1  2