Перейти к содержимому

Выборка товаров вместе с предложениями - цены, наличие, фильтр

Разбираемся, как получать торговые предложения к списку товаров, не устраивая по запросу на каждую позицию витрины.

Решение

Получаем предложения ко всему списку сразу:

$offers = CCatalogSKU::getOffersList(
$productIds, // массив идентификаторов товаров
5, // инфоблок товаров
['ACTIVE' => 'Y'], // фильтр по предложениям
['ID', 'NAME', 'QUANTITY'],
['CODE' => ['SIZE', 'COLOR']] // нужные свойства предложений
);

Вызов принимает список товаров и возвращает предложения, разложенные по ним. Запрос предложений внутри цикла по товарам - самая частая причина витрины на сотни запросов, и решается она именно этим вызовом.

Считаем цену «от» по вариантам:

foreach ($offers as $productId => $items) {
$prices = [];
foreach ($items as $offer) {
$price = CCatalogProduct::GetOptimalPrice($offer['ID'], 1);
$prices[] = $price['DISCOUNT_PRICE']; // цена с учётом скидок
}
printf("товар %d: от %.2f\n", $productId, $prices ? min($prices) : 0);
}

У товара с вариантами своей цены нет вовсе: цена лежит у его предложений. Пустая цена в карточке почти всегда означает, что её ищут у товара, а не у его вариантов.

Считаем наличие по вариантам:

$available = false;
foreach ($items as $offer) {
if ($offer['QUANTITY'] > 0) { $available = true; break; }
}
// товар доступен, пока доступен хотя бы один его вариант

Наличие товара складывается из наличия его отдельных вариантов. Товар с нулевым количеством у всех размеров недоступен целиком, и это же правило работает в отборе по наличию на витрине.

Фильтруем список по свойству предложения:

$APPLICATION->IncludeComponent('bitrix:catalog.section', '', [
'IBLOCK_ID' => 5,
'OFFERS_PROPERTY_CODE' => ['SIZE', 'COLOR'], // свойства вариантов в выдаче
'FILTER_NAME' => 'arrFilter', // отбор идёт через умный фильтр
]);

Отбор по свойствам вариантов делает умный фильтр, а не фильтр товаров. Условие, записанное в обычный фильтр по свойствам товара, до предложений просто не доходит и молча ничего не отбирает.

Смена цены предложения не сбрасывает кэш списка товаров сама по себе. Витрина после обмена показывает прежние цены до истечения времени жизни кэша, и это типичная жалоба «цены не обновились».

Список свойств вариантов стоит держать коротким. Каждое лишнее свойство в параметрах компонента - это ещё одно соединение таблиц на выборке, и на витрине в тридцать товаров разница видна невооружённым глазом.

Число запросов стоит проверять на списке из тридцати позиций, а не одной. Ошибка с запросом в цикле на одной карточке незаметна, а на витрине превращается в несколько сотен обращений к базе.

Типичные проблемы

В карточке товара пустая цена.

Цена лежит у торговых предложений, а не у самого товара. Товар с вариантами собственной цены не имеет вовсе, её берут у вариантов.

Витрина открывается по несколько секунд.

Предложения запрашиваются отдельным запросом для каждого товара списка. Их получают одним вызовом сразу для всего списка товаров.

Фильтр по размеру ничего не находит.

Условие записано в обычный фильтр по свойствам товара. Свойства вариантов отбирает умный фильтр, а не фильтр товаров.

Товар показан доступным, а купить нельзя.

Наличие взято у самого товара, а не у его вариантов. Доступность собирается из количества по каждому торговому предложению.

После обмена на витрине старые цены.

Кэш списка товаров не сброшен после смены цен у предложений. Он живёт своим временем жизни, и обмен с учётной системой его не трогает.

Частые вопросы

Как вывести все варианты в карточке?

Компонентом карточки с указанными свойствами предложений. Он сам собирает варианты и переключает цену при выборе.

Можно ли получить предложения запросом к инфоблоку?

Да, обычной выборкой по инфоблоку предложений с фильтром по связи. Штатный вызов удобнее: он сразу раскладывает результат по товарам.

Как показать остаток по каждому размеру?

Взять количество у каждого предложения и вывести рядом с вариантом. Товар при этом остаётся доступным, пока доступен хоть один размер.

Почему у части товаров нет вариантов?

Их и не завели: товар без предложений работает как обычный. Смешанный каталог - нормальная ситуация, шаблон должен уметь оба случая.

Смежное

Первоисточник