Понадобилось сделать сортировку товаров по популярности для клиента. Популярность = количество просмотров за день/неделю/месяц. Готового решения не нашёл, пришлось написать самому. Можно извернуться и вытаскивать статистику из модуля Статистики битрикса, но он отключен для экономии ресурсов. Общая статистика по сайту ведется всякими гуглами и метриками, так что модуль не нужен. Но статистика просмотров всё равно нужна.
Алогоритм получился такой.
Каждый день, в 00:00 берем статистику показов (SHOW_COUNTER) каждого товара и сохраняем его в отдельном инфоблоке в виде элемента с привязкой к товару. В отдельном сделал, потомучто показалось, что так удобнее - да и чтобы не грузить товар лишними свойствами. В этом инфоблоке получается ровно такое же количество элементов, сколько элементов в товарном инфоблоке. У каждого такого элемента есть свойства: STAT (строка с описанием, множественное), ITEM (привязка к элементам товарного инфоблока), NULL (число, начало отсчёта - ввёл это свойство, потомучто на день реализации уже было определенное количество показов, которое мне не нужно, а обнулять SHOW_COUNTER у товаров не мог, потомучто пока сортировка шла именно по этому полю). В свойство STAT каждый день попадает число с датой. Дата сохраняется в VALUE, количество просмотров в DESCRIPTION.
В это же время происходит пересчет просмотров за прошедший день/неделю/месяц.
Получив массив значений, вычисляем нужные нам числа за день/неделю/месяц и каждому товару кладём их в соответствующие свойства. Я создал у товаров 3 свойства DAY_SHOWS, WEEK_SHOWS и MONTH_SHOWS - в них каждую ночь и складываются вычесленные значения.
Теперь на сайте без лишних затрат я могу отсортировать товары по этим трём полям.
Все вычисления я обернул в функцию GetStat() и положил в файлик init.php, а запускается функция агентом. Можно было наверно вынести в отдельный файлик и запускать по крону, но мне так показалось проще.
Вот функция, вдруг кому пригодится. Только немного переделать под себя придётся.
Сделал как смог
Алогоритм получился такой.
Каждый день, в 00:00 берем статистику показов (SHOW_COUNTER) каждого товара и сохраняем его в отдельном инфоблоке в виде элемента с привязкой к товару. В отдельном сделал, потомучто показалось, что так удобнее - да и чтобы не грузить товар лишними свойствами. В этом инфоблоке получается ровно такое же количество элементов, сколько элементов в товарном инфоблоке. У каждого такого элемента есть свойства: STAT (строка с описанием, множественное), ITEM (привязка к элементам товарного инфоблока), NULL (число, начало отсчёта - ввёл это свойство, потомучто на день реализации уже было определенное количество показов, которое мне не нужно, а обнулять SHOW_COUNTER у товаров не мог, потомучто пока сортировка шла именно по этому полю). В свойство STAT каждый день попадает число с датой. Дата сохраняется в VALUE, количество просмотров в DESCRIPTION.
В это же время происходит пересчет просмотров за прошедший день/неделю/месяц.
Получив массив значений, вычисляем нужные нам числа за день/неделю/месяц и каждому товару кладём их в соответствующие свойства. Я создал у товаров 3 свойства DAY_SHOWS, WEEK_SHOWS и MONTH_SHOWS - в них каждую ночь и складываются вычесленные значения.
Теперь на сайте без лишних затрат я могу отсортировать товары по этим трём полям.
Все вычисления я обернул в функцию GetStat() и положил в файлик init.php, а запускается функция агентом. Можно было наверно вынести в отдельный файлик и запускать по крону, но мне так показалось проще.
Вот функция, вдруг кому пригодится. Только немного переделать под себя придётся.
function GetStat() { CModule::IncludeModule('iblock'); global $USER; $itemsIBlock = 17; // Инфоблок с товарами $statsIBlock = 74; // Инфоблок со статистикой $res = CIBlockElement::GetList(Array('SHOW_COUNTER' => 'asc'), Array("IBLOCK_ID"=>$itemsIBlock, "ACTIVE"=>"Y"), false, false, Array("ID", "NAME", "SHOW_COUNTER")); while($arFields = $res->GetNext()) { $item = array(); $itemres = array(); $stats = array(); $itemres = CIBlockElement::GetList(Array(), Array("IBLOCK_ID"=>$statsIBlock, "ACTIVE"=>"Y", "PROPERTY_ITEM"=>$arFields[ID]), false, false, Array("ID")); $item = $itemres->Fetch(); if ($item[ID]) { // Если по элементу уже собирается статистика // Сохранение статистики $stats_db = CIBlockElement::GetProperty($statsIBlock, $item[ID], array(), Array("CODE"=>"STAT")); while ($stat = $stats_db->GetNext()) { $stats[] = Array("VALUE" => $stat[VALUE], "DESCRIPTION" => $stat[DESCRIPTION]); } $stats[] = Array("VALUE" => date("d.m.Y", time()), "DESCRIPTION" => $arFields[SHOW_COUNTER]); CIBlockElement::SetPropertyValuesEx($item[ID], false, array('STAT' => $stats)); // Привязка статистики к товарам $stats_db = CIBlockElement::GetProperty($statsIBlock, $item[ID], array(), Array("CODE"=>"STAT")); $null_db = CIBlockElement::GetProperty($statsIBlock, $item[ID], array(), Array("CODE"=>"NULL")); $null = $null_db->Fetch(); $preday = 0; while ($stat = $stats_db->GetNext()) { $stat[DESCRIPTION] = intval($stat[DESCRIPTION]) - $null[VALUE] - $preday; $stats[] = Array("VALUE" => $stat[VALUE], "DESCRIPTION" => $stat[DESCRIPTION]); $preday = $stat[DESCRIPTION]; } arsort($stats); $day = reset($stats); $last = count($stats) - 1; $week = 0; for ($i=0; $i<=7; $i++) { $last--; $week = $week + $stats[$last][DESCRIPTION]; } $last = count($stats) - 1; for ($i=0; $i<=30; $i++) { $last--; $month = $month + $stats[$last][DESCRIPTION]; } CIBlockElement::SetPropertyValuesEx($arFields[ID], false, array('WEEK_SHOWS' => $week, 'MONTH_SHOWS' => $month, 'DAY_SHOWS' => $day[DESCRIPTION])); } else { // Если по элементу еще не собиралась статистика, создаём новый элемент. $el = new CIBlockElement; $PROP = array(); // Свойство STAT $PROP[496] = Array("VALUE" => date("d.m.Y", time()), "DESCRIPTION" => $arFields[SHOW_COUNTER]); // Свойство ITEM $PROP[497] = $arFields[ID]; // Свойство NULL $PROP[498] = $arFields[SHOW_COUNTER]; $arLoadProductArray = Array( "MODIFIED_BY" => $USER->GetID(), "IBLOCK_SECTION_ID" => false, "IBLOCK_ID" => $statsIBlock, "PROPERTY_VALUES"=> $PROP, "NAME" => $arFields[NAME] ); $el->Add($arLoadProductArray); } } return "GetStat();"; } |
Сделал как смог