В 1С-Битрикс из коробки нет встроенной функциональности для «Избранного», однако её можно легко реализовать несколькими способами. В этой статье мы разберём разные подходы, предоставим варианты кода и разберёмся, как избежать дублирования товаров при добавлении.

1. Общие принципы реализации «Избранного»
Хранение данных об избранных товарах
- Сессия или cookie. Простой способ для неавторизованных пользователей – хранить список избранных товаров в сессии или в cookie.
- Профиль пользователя. Для авторизованных пользователей удобнее хранить «Избранное» в базе, привязанной к пользователю, чтобы «Избранное» сохранялось между сессиями.
- Highload-блок (HL-блок). Продвинутый способ, который подойдёт, если вам требуется гибкая структура и вы планируете обрабатывать большие объёмы данных.
Проверка на дублирование
Необходимо убедиться, что при повторном нажатии кнопки «Добавить в избранное» один и тот же товар не добавляется вторично. Для этого обычно проверяют, есть ли уже ID товара в текущем списке «избранного».
Интеграция с интерфейсом
Можно использовать:
- Классические формы и отправку запросов через PHP (стандартные POST/GET запросы).
- Ajax-запросы через JavaScript (jQuery, fetch или XMLHttpRequest). Это часто удобнее для добавления товара «на лету» без перезагрузки страницы.
2. Пример реализации с сохранением в сессии (для неавторизованных пользователей)
2.1. Создание компонента или скрипта для добавления в избранное
Допустим, у вас есть кнопка «Добавить в избранное». Пусть её нажатие отправляет AJAX-запрос на сервер (в PHP-скрипт). Для наглядности сделаем отдельный файл ajax_favorite.php
.
Шаг 1: Создадим AJAX-скрипт ajax_favorite.php
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
// Проверяем, подключены ли необходимые модули (если необходимо)
if(!\Bitrix\Main\Loader::includeModule("iblock")) {
echo json_encode(["status" => "error", "message" => "Модуль iblock не подключен"]);
die();
}
// Идентификатор товара, который хотим добавить
$productId = (int)$_REQUEST["product_id"];
// Стартуем сессию, если она не запущена
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
if (!isset($_SESSION["FAVORITE_PRODUCTS"])) {
$_SESSION["FAVORITE_PRODUCTS"] = [];
}
// Проверка, есть ли уже такой товар в избранном
if (!in_array($productId, $_SESSION["FAVORITE_PRODUCTS"])) {
$_SESSION["FAVORITE_PRODUCTS"][] = $productId;
echo json_encode(["status" => "success", "message" => "Товар добавлен в избранное"]);
} else {
echo json_encode(["status" => "warning", "message" => "Товар уже в избранном"]);
}
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
Шаг 2: Добавим кнопку на сайте
<button
class="add-to-favorite"
data-product-id="<?= $arItem['ID'] ?>"
>
Добавить в избранное
</button>
Шаг 3: Реализуем AJAX-запрос через JavaScript
<script>
document.addEventListener('DOMContentLoaded', function() {
const buttons = document.querySelectorAll('.add-to-favorite');
buttons.forEach(function(button) {
button.addEventListener('click', function() {
const productId = this.getAttribute('data-product-id');
fetch('/ajax_favorite.php?product_id=' + productId, {
method: 'GET'
})
.then(response => response.json())
.then(data => {
alert(data.message);
})
.catch(error => {
console.error('Ошибка:', error);
});
});
});
});
</script>
Что происходит?
- При клике на кнопку формируется GET-запрос вида
/ajax_favorite.php?product_id=123
. - На сервере товар проверяется на наличие в сессии (в массиве
$_SESSION["FAVORITE_PRODUCTS"]
). - Если товар отсутствует, он добавляется в массив и возвращается сообщение об успехе.
- Если товар уже есть, возвращается предупреждение, что он уже добавлен.
Минусы этого подхода:
- У неавторизованных пользователей «Избранное» хранится только до окончания сессии или до момента, пока пользователь не очистит куки, и не всегда удобно переносить эти данные на другой компьютер или другое устройство.
3. Хранение «Избранного» в базе (для авторизованных пользователей)
3.1. Использование пользовательских полей в пользователях
В 1С-Битрикс мы можем добавить пользовательское поле (User Field), например UF_FAVORITE_PRODUCTS
, и сохранять туда массив ID товаров.
- Заходим в админку: Настройки → Пользователи → Пользовательские поля → Добавить пользовательское поле.
- Указываем там параметр Код поля (например,
UF_FAVORITE_PRODUCTS
) и тип «Привязка к элементам» или «Строка» (если нужна гибкость – можно хранить строкой в JSON-формате).
Пример записи данных в пользовательское поле (PHP):
<?php
// Проверяем модули
\Bitrix\Main\Loader::includeModule("main");
\Bitrix\Main\Loader::includeModule("iblock");
// Получаем ID авторизованного пользователя
global $USER;
if (!$USER->IsAuthorized()) {
die("Пользователь не авторизован!");
}
$userId = $USER->GetID();
$productId = (int)$_REQUEST["product_id"];
// Получаем данные пользователя
$rsUser = CUser::GetByID($userId);
$arUser = $rsUser->Fetch();
// Предположим, что в UF_FAVORITE_PRODUCTS хранится массив ID
$favoriteProducts = $arUser["UF_FAVORITE_PRODUCTS"];
if (!is_array($favoriteProducts)) {
$favoriteProducts = [];
}
// Проверка на дублирование
if (!in_array($productId, $favoriteProducts)) {
$favoriteProducts[] = $productId;
// Обновляем данные пользователя
$user = new CUser;
$fields = [
"UF_FAVORITE_PRODUCTS" => $favoriteProducts
];
$user->Update($userId, $fields);
if ($user->LAST_ERROR) {
echo json_encode(["status" => "error", "message" => $user->LAST_ERROR]);
} else {
echo json_encode(["status" => "success", "message" => "Товар добавлен в избранное"]);
}
} else {
echo json_encode(["status" => "warning", "message" => "Товар уже в избранном"]);
}
Таким образом, список избранного «привязан» к учётной записи пользователя. Пользователь может авторизоваться с другого устройства – и увидит свой список избранного.
3.2. Хранение данных в Highload-блоке (HL-блоке)
Если вам нужен более гибкий способ управления «Избранным» (например, отдельная таблица с полями, датой добавления, статусом и т.д.), в 1С-Битрикс можно создать Highload-блок.
Шаг 1: Создаём HL-блок в административной части
- Заходим в админку: Настройки → Высоконагруженные блоки (Highload-блоки) → Добавить highload-блок.
- Задаём название, например,
FavoriteProducts
. - Создаём поля:
UF_USER_ID
(Тип: целое число, привязка к пользователю или просто ID)UF_PRODUCT_ID
(Тип: целое число, ID товара)- при необходимости другие поля.
Шаг 2: Пишем PHP-код для добавления в HL-блок
<?php
use Bitrix\Main\Loader;
use Bitrix\Highloadblock as HL;
use Bitrix\Main\Entity;
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
Loader::includeModule("highloadblock");
// ID вашего HL-блока, который вы создали в админке
const HL_BLOCK_ID = 1; // замените 1 на ваш реальный ID
// Функция для получения сущности HL-блока
function getHlEntity($hlBlockId) {
$hlblock = HL\HighloadBlockTable::getById($hlBlockId)->fetch();
return HL\HighloadBlockTable::compileEntity($hlblock);
}
// Получаем сущность
$entity = getHlEntity(HL_BLOCK_ID);
$entityClass = $entity->getDataClass();
// Получаем данные
global $USER;
if (!$USER->IsAuthorized()) {
die(json_encode(["status" => "error", "message" => "Пользователь не авторизован"]));
}
$userId = $USER->GetID();
$productId = (int)$_REQUEST["product_id"];
// Проверяем, нет ли уже записи
$res = $entityClass::getList([
"select" => ["ID", "UF_USER_ID", "UF_PRODUCT_ID"],
"filter" => ["=UF_USER_ID" => $userId, "=UF_PRODUCT_ID" => $productId],
"limit" => 1,
]);
if ($item = $res->fetch()) {
// Нашли запись - значит товар уже в избранном
echo json_encode(["status" => "warning", "message" => "Товар уже в избранном"]);
} else {
// Добавляем запись
$result = $entityClass::add([
"UF_USER_ID" => $userId,
"UF_PRODUCT_ID" => $productId,
]);
if ($result->isSuccess()) {
echo json_encode(["status" => "success", "message" => "Товар добавлен в избранное"]);
} else {
$errors = $result->getErrorMessages();
echo json_encode(["status" => "error", "message" => implode(", ", $errors)]);
}
}
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
Что делать с неавторизованными пользователями?
- Можно сохранять данные в HL-блоке с использованием временного ключа (генерировать уникальный идентификатор, хранить его в cookie). При авторизации «переводить» избранное из временного ID в ID реального пользователя. Это более сложная схема, но гибкая и близкая к тому, как реализованы корзины в Bitrix.
4. Проверка на дублирование товаров
Как видно из примеров, проверка может осуществляться различными способами:
- В сессии – с помощью
in_array($productId, $_SESSION["FAVORITE_PRODUCTS"])
. - В пользовательском поле – проверять через
in_array($productId, $arUser["UF_FAVORITE_PRODUCTS"])
. - В HL-блоке – запросом типа
filter
c=UF_USER_ID
и=UF_PRODUCT_ID
.
Важно убедиться, что перед добавлением вы всегда проверяете, присутствует ли уже этот товар в «Избранном», и если да – возвращаете сообщение пользователю, чтобы избежать дублей.
5. Вывод списка «Избранного» на сайте
5.1. Если используем сессию (для неавторизованных)
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
$favoriteProducts = $_SESSION["FAVORITE_PRODUCTS"] ?? []; // если такого ключа нет, берём пустой массив
if (!empty($favoriteProducts)) {
// Предположим, товары лежат в инфоблоке с ID = 2, выведем их названия
$arSelect = ["ID", "NAME", "DETAIL_PAGE_URL"];
$arFilter = ["IBLOCK_ID" => 2, "ID" => $favoriteProducts];
$res = CIBlockElement::GetList([], $arFilter, false, false, $arSelect);
while ($ob = $res->GetNextElement()) {
$arFields = $ob->GetFields();
echo '<div>';
echo '<a href="'.$arFields["DETAIL_PAGE_URL"].'">'.$arFields["NAME"].'</a>';
echo '</div>';
}
} else {
echo "У вас нет товаров в избранном";
}
5.2. Если используем пользовательское поле
global $USER;
if ($USER->IsAuthorized()) {
$userId = $USER->GetID();
$rsUser = CUser::GetByID($userId);
$arUser = $rsUser->Fetch();
$favoriteProducts = $arUser["UF_FAVORITE_PRODUCTS"];
if (!empty($favoriteProducts)) {
$arSelect = ["ID", "NAME", "DETAIL_PAGE_URL"];
$arFilter = ["IBLOCK_ID" => 2, "ID" => $favoriteProducts];
$res = CIBlockElement::GetList([], $arFilter, false, false, $arSelect);
while ($ob = $res->GetNextElement()) {
$arFields = $ob->GetFields();
echo '<div>';
echo '<a href="'.$arFields["DETAIL_PAGE_URL"].'">'.$arFields["NAME"].'</a>';
echo '</div>';
}
} else {
echo "У вас нет товаров в избранном";
}
} else {
echo "Авторизуйтесь, чтобы увидеть избранное";
}
5.3. Если используем HL-блок
use Bitrix\Main\Loader;
use Bitrix\Highloadblock as HL;
use Bitrix\Main\Entity;
Loader::includeModule("highloadblock");
Loader::includeModule("iblock");
global $USER;
if ($USER->IsAuthorized()) {
$userId = $USER->GetID();
$hlblockId = 1; // ваш ID
$hlblock = HL\HighloadBlockTable::getById($hlblockId)->fetch();
$entity = HL\HighloadBlockTable::compileEntity($hlblock);
$entityClass = $entity->getDataClass();
// Получаем все товары для данного пользователя
$res = $entityClass::getList([
"select" => ["ID", "UF_PRODUCT_ID"],
"filter" => ["=UF_USER_ID" => $userId],
]);
$productIds = [];
while ($item = $res->fetch()) {
$productIds[] = $item["UF_PRODUCT_ID"];
}
if (!empty($productIds)) {
// Выбираем из инфоблока
$arSelect = ["ID", "NAME", "DETAIL_PAGE_URL"];
$arFilter = ["IBLOCK_ID" => 2, "ID" => $productIds];
$dbElements = CIBlockElement::GetList([], $arFilter, false, false, $arSelect);
while ($ob = $dbElements->GetNextElement()) {
$arFields = $ob->GetFields();
echo '<div>';
echo '<a href="'.$arFields["DETAIL_PAGE_URL"].'">'.$arFields["NAME"].'</a>';
echo '</div>';
}
} else {
echo "У вас нет товаров в избранном";
}
} else {
echo "Авторизуйтесь, чтобы увидеть избранное";
}
6. Удаление из «Избранного»
Для реализации удаления из «Избранного» мы используем очень похожий подход, что и для добавления. Просто логика будет обратной: при получении ID товара мы проверяем, находится ли этот товар в избранном, и при наличии — удаляем.
6.1. Удаление из «Избранного» в сессии (неавторизованные пользователи)
Если вы храните ID товаров в $_SESSION["FAVORITE_PRODUCTS"]
, то удаление выглядит так:
<?php
// remove_favorite.php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
// Стартуем сессию, если вдруг она не запущена
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
$productId = (int)$_REQUEST["product_id"];
// Проверяем, что массив существует
if (!isset($_SESSION["FAVORITE_PRODUCTS"])) {
$_SESSION["FAVORITE_PRODUCTS"] = [];
}
// Получаем индекс товара в массиве (если он там есть)
$index = array_search($productId, $_SESSION["FAVORITE_PRODUCTS"]);
if ($index !== false) {
// Удаляем элемент из массива
unset($_SESSION["FAVORITE_PRODUCTS"][$index]);
// Сбрасываем ключи массива, чтобы индексы были последовательными
$_SESSION["FAVORITE_PRODUCTS"] = array_values($_SESSION["FAVORITE_PRODUCTS"]);
echo json_encode(["status" => "success", "message" => "Товар удалён из избранного"]);
} else {
echo json_encode(["status" => "warning", "message" => "Товар не найден в избранном"]);
}
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
Примечание: для удобства можно сделать единый скрипт, который принимает действие
action=add
илиaction=remove
. Но иногда проще и понятнее создавать два отдельных файла.
AJAX-запрос (JavaScript) для удаления может выглядеть так же, как и для добавления, только с другим URL (или с указанием другого параметра):
<script>
function removeFromFavorite(productId) {
fetch('/remove_favorite.php?product_id=' + productId, {
method: 'GET'
})
.then(response => response.json())
.then(data => {
alert(data.message);
})
.catch(error => console.error('Ошибка:', error));
}
</script>
6.2. Удаление из «Избранного» в пользовательском поле пользователя
Допустим, вы храните список ID товаров в пользовательском поле UF_FAVORITE_PRODUCTS
(типа «Привязка к элементам» или «Строка»). Тогда удаление будет выглядеть так:
<?php
// remove_favorite_userfield.php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
\Bitrix\Main\Loader::includeModule("main");
\Bitrix\Main\Loader::includeModule("iblock");
global $USER;
if (!$USER->IsAuthorized()) {
echo json_encode(["status" => "error", "message" => "Необходима авторизация"]);
die();
}
$userId = $USER->GetID();
$productId = (int)$_REQUEST["product_id"];
// Получаем текущие избранные товары
$rsUser = CUser::GetByID($userId);
$arUser = $rsUser->Fetch();
$favoriteProducts = $arUser["UF_FAVORITE_PRODUCTS"];
// Если пусто, сразу возвращаем предупреждение
if (!is_array($favoriteProducts) || empty($favoriteProducts)) {
echo json_encode(["status" => "warning", "message" => "У вас нет товаров в избранном"]);
die();
}
// Ищем товар в списке
$key = array_search($productId, $favoriteProducts);
if ($key !== false) {
unset($favoriteProducts[$key]);
// Сбрасываем ключи, если требуется
$favoriteProducts = array_values($favoriteProducts);
$user = new CUser;
$fields = ["UF_FAVORITE_PRODUCTS" => $favoriteProducts];
$user->Update($userId, $fields);
if ($user->LAST_ERROR) {
echo json_encode(["status" => "error", "message" => $user->LAST_ERROR]);
} else {
echo json_encode(["status" => "success", "message" => "Товар удалён из избранного"]);
}
} else {
echo json_encode(["status" => "warning", "message" => "Товар не найден в избранном"]);
}
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
6.3. Удаление из «Избранного» в HL-блоке
При использовании Highload-блока мы храним каждую запись отдельно — «ID пользователя + ID товара». Удаление — это удаление соответствующей записи.
<?php
// remove_favorite_hl.php
use Bitrix\Main\Loader;
use Bitrix\Highloadblock as HL;
use Bitrix\Main\Entity;
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
Loader::includeModule("highloadblock");
const HL_BLOCK_ID = 1; // ID вашего HL-блока
// Получение класса сущности
function getHlEntity($hlBlockId) {
$hlblock = HL\HighloadBlockTable::getById($hlBlockId)->fetch();
return HL\HighloadBlockTable::compileEntity($hlblock);
}
$entity = getHlEntity(HL_BLOCK_ID);
$entityClass = $entity->getDataClass();
global $USER;
if (!$USER->IsAuthorized()) {
echo json_encode(["status" => "error", "message" => "Необходима авторизация"]);
die();
}
$userId = $USER->GetID();
$productId = (int)$_REQUEST["product_id"];
// Ищем запись
$res = $entityClass::getList([
"select" => ["ID"],
"filter" => [
"=UF_USER_ID" => $userId,
"=UF_PRODUCT_ID" => $productId
],
"limit" => 1
]);
if ($row = $res->fetch()) {
// Удаляем
$deleteResult = $entityClass::delete($row["ID"]);
if ($deleteResult->isSuccess()) {
echo json_encode(["status" => "success", "message" => "Товар удалён из избранного"]);
} else {
$errors = $deleteResult->getErrorMessages();
echo json_encode(["status" => "error", "message" => implode(", ", $errors)]);
}
} else {
echo json_encode(["status" => "warning", "message" => "Товар не найден в избранном"]);
}
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
7. Объединение «Избранного» при авторизации
Один из самых удобных сценариев — когда неавторизованный пользователь может добавлять товары в избранное (храним в сессии или cookies), а при авторизации вся эта информация «сливается» в ту структуру, что хранится у авторизованного пользователя (пользовательское поле / HL-блок).
7.1. Общая схема
- Пользователь (гость) переходит на сайт, добавляет товары в избранное. Эти ID хранятся в
$_SESSION["FAVORITE_PRODUCTS"]
. - Пользователь авторизуется. На событии авторизации (или сразу после авторизации) мы:
- Берём товары из сессии.
- Добавляем их в хранилище, закреплённое за пользователем (в HL-блоке или в
UF_FAVORITE_PRODUCTS
). - Очищаем сессию или же оставляем её для синхронизации.
7.2. Пример кода на событии OnAfterUserAuthorize
Bitrix позволяет «подцепиться» к событию авторизации пользователя: документация по событиям (если вдруг понадобятся детали). Ниже упрощённый пример:
<?php
// local/php_interface/init.php
AddEventHandler("main", "OnAfterUserAuthorize", "MergeFavoriteAfterAuth");
function MergeFavoriteAfterAuth($arParams)
{
global $USER;
// Если авторизация прошла успешно:
if ($arParams["user_fields"]["ID"] > 0) {
$userId = $USER->GetID();
// Берём товары из сессии
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
if (!empty($_SESSION["FAVORITE_PRODUCTS"]) && is_array($_SESSION["FAVORITE_PRODUCTS"])) {
$favoritesFromSession = $_SESSION["FAVORITE_PRODUCTS"];
// --- Для примера с пользовательским полем ---
$rsUser = CUser::GetByID($userId);
$arUser = $rsUser->Fetch();
$favoriteProductsUser = $arUser["UF_FAVORITE_PRODUCTS"];
if (!is_array($favoriteProductsUser)) {
$favoriteProductsUser = [];
}
// Сольём массивы и удалим дубли
$merged = array_unique(array_merge($favoriteProductsUser, $favoritesFromSession));
// Сохраняем
$user = new CUser;
$fields = [
"UF_FAVORITE_PRODUCTS" => $merged
];
$user->Update($userId, $fields);
// Очищаем сессию или оставляем её, но обычно очищаем:
unset($_SESSION["FAVORITE_PRODUCTS"]);
}
}
}
Если у вас HL-блок, то, соответственно, вместо записи в
UF_FAVORITE_PRODUCTS
вам нужно будет сделатьSELECT
иINSERT
через соответствующий highload-класс, аналогично тому, как это делается при добавлении.
Таким образом, если пользователь до авторизации добавил 3 товара, а в его профиле уже есть 2 товара, в результате будет 5 товаров без дублирования.
8. Отображение иконок и состояния «Избранного»
Часто на сайте рядом с товаром рисуют сердечко (иконку избранного). Если товар уже находится в избранном, сердечко делают «закрашенным» (активным). Есть несколько способов это отобразить:
8.1. Серверный рендеринг (PHP)
Вы на стороне сервера при формировании каталога или списка товаров проверяете, есть ли ID товара в списке избранного (сессия, пользовательское поле или HL-блок). Если есть — добавляете класс favorite-active
, иначе favorite-inactive
.
<?php
// Пример (упрощённый)
// Пусть $arItem['ID'] — ID товара
$isFavorite = false;
if ($USER->IsAuthorized()) {
// Проверяем в HL-блоке или пользовательском поле
// или заранее подготовили массив $userFavorites
$isFavorite = in_array($arItem['ID'], $userFavorites);
} else {
// Проверяем в сессии
$isFavorite = in_array($arItem['ID'], $_SESSION["FAVORITE_PRODUCTS"]);
}
?>
<div class="product-item">
<span class="product-name"><?= $arItem['NAME'] ?></span>
<button
class="favorite-btn <?= $isFavorite ? 'favorite-active' : 'favorite-inactive' ?>"
data-product-id="<?= $arItem['ID'] ?>"
>
♥
</button>
</div>
8.2. Клиентский рендеринг (JavaScript + AJAX)
- При загрузке страницы можно по AJAX запросить список ID товаров в избранном и затем на клиенте динамически проставить класс «активный» для тех товаров, что вернутся в этом списке.
- Это удобно, когда нужно быстро менять состояние без перезагрузки страницы.
Для большего удобства в UI можно использовать ту же кнопку, что и для добавления/удаления, просто при клике меняем класс и отправляем соответствующий AJAX-запрос («добавить» или «удалить»).
8.3. Пример клиентского подхода
<script>
document.addEventListener("DOMContentLoaded", function() {
// Предположим, что у нас есть глобальный массив productIDs
// со всеми ID товаров на странице
// 1) Запрашиваем у сервера текущие избранные товары
fetch('/ajax_get_favorites.php')
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
const favoriteList = data.favorites; // массив ID товаров в избранном
// 2) Ставим нужные классы
favoriteList.forEach(function(favId) {
let btn = document.querySelector(`.favorite-btn[data-product-id="${favId}"]`);
if (btn) {
btn.classList.remove('favorite-inactive');
btn.classList.add('favorite-active');
}
});
}
});
});
</script>
А в ajax_get_favorites.php
мы возвращаем список избранных товаров для текущего пользователя (либо из сессии, либо из БД).
9. Оптимизация
Когда проект растёт, вопросов с избранным может стать много. Что учесть:
9.1. Использование HL-блоков
При большом количестве пользователей и товаров лучше хранить «Избранное» в HL-блоке:
- Можно индексировать поля
UF_USER_ID
иUF_PRODUCT_ID
. - Делать выборки по фильтру гораздо быстрее, чем в обычных пользовательских полях, если данных очень много.
9.2. Кеширование
- Если у вас есть постоянные запросы на вывод «Избранного», можно кешировать результаты — например, сохранять итоговый список товаров для конкретного пользователя. Это особенно актуально, если пользователь редко меняет «Избранное», а просмотров страниц у него много.
- В Bitrix используется механизм компонентного кеширования или статического кеширования с помощью класса
CPHPCache
.
9.3. Прочие моменты
- При больших объёмах данных желательно оптимизировать сами SQL-запросы (например, не вызывать
CIBlockElement::GetList
для каждого товара, а сразу забирать их пакетно). - Не хранить лишние данные в сессии (только ID товаров), чтобы не перегружать её.
Итог
Функциональность «Избранного» можно расширять и дополнять по мере роста вашего проекта. Основные «фишки» для продвинутого использования:
- Удаление — аналогично добавлению, только выполняется
unset
в массиве (сессия, пользовательское поле) илиdelete
в HL-блоке. - Объединение «Избранного» — переносим данные из гостевой сессии в профиль пользователя при авторизации с помощью события
OnAfterUserAuthorize
. - Отображение иконок — показываем пользователю статус «в избранном / не в избранном» по данным с сервера или через AJAX.
- Оптимизация — используем HL-блоки, индексы, кеширование и пакеты запросов при больших объёмах.
Таким образом, вы можете обеспечить удобную работу пользователям, избежать дублирования товаров и сохранить высокую производительность сайта.
7. Заключение
Функциональность «Избранного» в 1С-Битрикс можно реализовать разными способами. Самый простой – хранить избранное в сессии (или cookie) для неавторизованных пользователей. Более надёжный способ – хранить данные в базе, связанной с пользователем. Если проект крупный и нужно расширенное управление, то идеальный вариант – Highload-блок, позволяющий гибко хранить данные и обрабатывать их при большом трафике.
Главное во всех вариантах – не забывать проверять, не добавлен ли товар уже в избранное. Это поможет избежать дублей и сохранить удобство для пользователей.
Используйте подход, который подходит под задачи вашего проекта, и не бойтесь комбинировать их (например, гостевое избранное в сессии + перенос в базу после авторизации). Благодаря гибкой структуре 1С-Битрикс вы сможете настроить систему под любые нужды и обеспечить пользователям удобный функционал для сохранения любимых товаров.