Разработка системы рейтингов товаров 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка системы рейтингов товаров 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка системы рейтингов товаров 1С-Битрикс

Рейтинг товара — агрегированная оценка, которая влияет на ранжирование в каталоге, выводится в карточке и в списках. В 1С-Битрикс есть модуль vote (голосования), но для рейтинга товаров он избыточен и плохо интегрируется с каталогом. Практичнее хранить оценки в отдельной таблице и агрегировать значение в свойство инфоблока.

Архитектура хранения оценок

Таблица b_product_vote для индивидуальных оценок:

Поле Тип Назначение
ID int Первичный ключ
PRODUCT_ID int ID товара
USER_ID int ID пользователя (NULL = гость)
IP varchar(45) IP-адрес (для гостей и анти-накрутки)
RATING tinyint Оценка 1–5
CREATED_AT datetime Когда проголосовал

ORM-класс ProductVoteTable наследуется от \Bitrix\Main\ORM\Data\DataManager.

В инфоблоке товаров добавляются два свойства числового типа:

  • RATING_AVG — средняя оценка (float, обновляется после каждого голосования)
  • RATING_COUNT — количество оценок

Это позволяет сортировать и фильтровать по рейтингу через стандартный CIBlockElement::GetList() без JOIN.

Алгоритм голосования

Голосование реализуется через AJAX-запрос. Компонент отдаёт форму со звёздочками, клик отправляет POST на контроллер:

// local/ajax/product_vote.php
\Bitrix\Main\Loader::includeModule('main');
\Bitrix\Main\Loader::includeModule('catalog');

$productId = (int)($_POST['product_id'] ?? 0);
$rating    = (int)($_POST['rating'] ?? 0);

if ($rating < 1 || $rating > 5 || $productId <= 0) {
    echo json_encode(['success' => false, 'error' => 'invalid_data']);
    exit;
}

$userId = $GLOBALS['USER']->GetID() ?: null;
$ip     = \Bitrix\Main\Context::getCurrent()->getRequest()->getRemoteAddress();

// Проверка: уже голосовал?
$existing = ProductVoteTable::getList([
    'filter' => ['=PRODUCT_ID' => $productId, '=USER_ID' => $userId ?: false, '=IP' => $ip],
    'limit'  => 1,
])->fetch();

if ($existing && $userId === null) {
    echo json_encode(['success' => false, 'error' => 'already_voted']);
    exit;
}

Для авторизованных пользователей проверяем по USER_ID. Для гостей — по IP. Авторизованный пользователь может изменить свою оценку (обновляем существующую запись вместо создания новой).

Пересчёт агрегированного рейтинга

После каждого голосования обновляем агрегаты:

function updateProductRating(int $productId): void
{
    $conn = \Bitrix\Main\Application::getConnection();
    $row = $conn->query(
        "SELECT AVG(RATING) as AVG_RATING, COUNT(*) as CNT
         FROM b_product_vote
         WHERE PRODUCT_ID = {$productId}"
    )->fetch();

    \CIBlockElement::SetPropertyValuesEx($productId, false, [
        'RATING_AVG'   => round((float)$row['AVG_RATING'], 2),
        'RATING_COUNT' => (int)$row['CNT'],
    ]);
}

SetPropertyValuesEx работает быстрее, чем Update() всего элемента — он обновляет только указанные свойства.

Визуализация: звёздочный виджет

На фронтенде рейтинг отображается как набор SVG-звёзд. Логика частичного заполнения: для оценки 4.3 четыре звезды заполнены полностью, пятая — на 30%. Реализуется через CSS-clip или SVG-gradient с шириной, пропорциональной дробной части.

Компонент для вывода рейтинга в карточке товара и в списке принимает параметры:

$APPLICATION->IncludeComponent('custom:product.rating', '', [
    'PRODUCT_ID'    => $arResult['ID'],
    'SHOW_FORM'     => $USER->IsAuthorized() ? 'Y' : 'N',
    'CURRENT_RATING' => $arResult['PROPERTIES']['RATING_AVG']['VALUE'],
    'VOTE_COUNT'    => $arResult['PROPERTIES']['RATING_COUNT']['VALUE'],
]);

Защита от накрутки

Ограничения по IP хороши для гостей, но не для организованных накруток:

  • Для авторизованных — одна оценка на товар (жёсткая проверка по USER_ID + PRODUCT_ID).
  • Ограничение: нельзя голосовать за товар, который ни разу не просматривался (проверка через b_stat_session или кастомную таблицу просмотров).
  • Опционально: разрешить голосование только пользователям, купившим товар (аналогично верификации в системе отзывов).

Сроки разработки

Масштаб Состав Срок
Базовый ORM-модель, AJAX-голосование, звёздочный виджет, агрегация в свойство 3–4 дня
Полный Изменение оценки, защита от накрутки, сортировка в каталоге по рейтингу, история голосований 5–7 дней