Yandex Metrika
sanches.free 1 просмотр

Сортировка каталога по числу добавлений в корзину в Битрикс

Идея

Чтобы витрина показывала «любимые» позиции первыми, удобно заранее накапливать метрику: сколько раз товар попадал в корзину. Хранить это как числовое свойство элемента каталога и сортировать по нему в параметрах компонента проще и быстрее, чем на лету считать строки таблицы b_sale_basket для каждой выборки.

Свойство в инфоблоке

Создайте свойство типа «Число» с символьным кодом, например BASKET_HIT_NUM, и включите участие в сортировке в настройках инфоблока. Идентификатор торгового каталога в примерах замените на свой — переменная $storeCatalogIblockId.

Инкремент при добавлении позиции

Подключите обработчик к событию после добавления записи корзины. Внутри загружаются модули iblock и sale, читается текущее значение свойства и увеличивается на единицу для PRODUCT_ID из полей события.

use Bitrix\Main\Entity\Event;
use Bitrix\Main\EventManager;

$dispatcher = EventManager::getInstance();
$dispatcher->addEventHandler(
    'sale',
    '\\Bitrix\\Sale\\Internals\\Basket::OnAfterAdd',
    ['BasketAddCounter', 'incrementHitProperty']
);

class BasketAddCounter
{
    public static function incrementHitProperty(Event $event)
    {
        \Bitrix\Main\Loader::includeModule('iblock');

        $row = $event->getParameter('fields');
        if (empty($row['PRODUCT_ID'])) {
            return;
        }

        $storeCatalogIblockId = 1; // ID инфоблока каталога
        $propertyCode = 'BASKET_HIT_NUM';

        $prior = \CIBlockElement::GetProperty(
            $storeCatalogIblockId,
            (int)$row['PRODUCT_ID'],
            [],
            ['CODE' => $propertyCode]
        )->fetch();

        $baseline = isset($prior['VALUE']) && $prior['VALUE'] !== ''
            ? (int)$prior['VALUE']
            : 0;

        \CIBlockElement::SetPropertyValuesEx(
            (int)$row['PRODUCT_ID'],
            $storeCatalogIblockId,
            [$propertyCode => $baseline + 1]
        );
    }
}

Разовая инициализация из открытых корзин

Если нужно выставить стартовые значения по уже накопленным «висящим» корзинам без заказа, можно пройти агрегат по таблице корзины и записать свойство пакетом. Отфильтруйте сайт через SITE_ID или конкретный LID; для строк без оформленного заказа обычно используют фильтр '=ORDER_ID' => false (в отдельных версиях встречается сравнение с null — сверьтесь со схемой своей установки).

\Bitrix\Main\Loader::includeModule('iblock');
\Bitrix\Main\Loader::includeModule('sale');

use Bitrix\Main\Entity\ExpressionField;
use Bitrix\Sale\Internals\BasketTable;

$storeCatalogIblockId = 1;
$propertyCode = 'BASKET_HIT_NUM';

$rollup = BasketTable::getList([
    'filter' => [
        '=ORDER_ID' => false,
        '=LID' => 's1',
    ],
    'select' => ['PRODUCT_ID', 'ROW_QTY'],
    'runtime' => [
        new ExpressionField('ROW_QTY', 'COUNT(*)'),
    ],
    'group' => ['PRODUCT_ID'],
]);

while ($bucket = $rollup->fetch()) {
    \CIBlockElement::SetPropertyValuesEx(
        (int)$bucket['PRODUCT_ID'],
        $storeCatalogIblockId,
        [$propertyCode => (int)$bucket['ROW_QTY']]
    );
}

Сортировка в компоненте списка

После того как свойство участвует в индексах свойств инфоблока, передайте его в параметры catalog.section (или родительского комплексного компонента): основное поле сортировки — псевдоним свойства через префикс PROPERTY_, порядок — по убыванию для популярных записей первыми.

'ELEMENT_SORT_FIELD' => 'PROPERTY_BASKET_HIT_NUM',
'ELEMENT_SORT_ORDER' => 'DESC',

На что обратить внимание

  • Если SKU лежит в отдельном инфоблоке, свойство нужно вести на том уровне, по которому реально фильтрует каталог на витрине.
  • При активном обмене с 1С убедитесь, что обновление реквизитов не обнуляет пользовательские свойства без вашего участия.
  • В проектах с очень высоким трафиком десятки обновлений свойства в секунду можно вынести в очередь или агента; для большинства витрин прямой SetPropertyValuesEx достаточен.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии