В каталоге Bitrix товар и его торговые предложения хранятся в связанных инфоблоках. Сначала создаётся элемент товара, затем элемент предложения со свойством привязки, после чего предложению добавляют параметры каталога и цену. Ниже разобран старый API из заметки 2017 года; в новом коде выбирайте API вашей версии ядра.
Условия перед запуском
- Пролог Bitrix подключён; код исполняется в доверенном обработчике с нужными правами, а не по открытому HTTP-запросу.
- Инфоблок предложений уже настроен как каталог и связан с инфоблоком товаров.
- Число
3— пример идентификатора; замените его значением из своего проекта. - Пример создаёт новые элементы при каждом запуске. Для повторяемого импорта нужен внешний ключ и поиск существующих записей.
Создание и последовательные проверки
<?php
use Bitrix\Main\Loader;
if (!Loader::includeModule('iblock') || !Loader::includeModule('catalog')) {
throw new RuntimeException('Не загружены модули iblock/catalog');
}
$offersIblockId = 3;
$catalog = CCatalog::GetByID($offersIblockId);
if (!$catalog || empty($catalog['PRODUCT_IBLOCK_ID']) || empty($catalog['SKU_PROPERTY_ID'])) {
throw new RuntimeException('Не настроена связь инфоблоков товара и предложений');
}
$product = new CIBlockElement();
$productId = $product->Add([
'NAME' => 'Товар',
'IBLOCK_ID' => (int) $catalog['PRODUCT_IBLOCK_ID'],
'ACTIVE' => 'Y',
]);
if (!$productId) {
throw new RuntimeException('Товар: ' . $product->LAST_ERROR);
}
$offer = new CIBlockElement();
$offerId = $offer->Add([
'NAME' => 'Торговое предложение',
'IBLOCK_ID' => $offersIblockId,
'ACTIVE' => 'Y',
'PROPERTY_VALUES' => [(int) $catalog['SKU_PROPERTY_ID'] => $productId],
]);
if (!$offerId) {
throw new RuntimeException('Предложение: ' . $offer->LAST_ERROR);
}
if (!CCatalogProduct::Add(['ID' => $offerId, 'VAT_INCLUDED' => 'Y'])) {
throw new RuntimeException('Не добавлены параметры предложения в каталог');
}
if (!CPrice::SetBasePrice($offerId, 100.50, 'RUB')) {
throw new RuntimeException('Не установлена базовая цена предложения');
}
// Успех: $productId и $offerId содержат созданные идентификаторы.
?>Важно, что во всех последних вызовах используется один $offerId. Проверка добавления параметров и проверка цены разделены: успешная установка цены не должна попадать в ветку ошибки.
Границы этого примера
Несколько успешных вызовов с последующей ошибкой могут оставить частично созданные данные. Перед применением в импорте продумайте транзакцию и компенсацию с учётом обработчиков событий вашей установки. Не удаляйте автоматически уже существующий товар при сбое предложения. Для промышленного сценария также нужны количество, доступность, свойства и правила налогообложения именно вашего каталога.
Документация CCatalogProduct::Add помечает метод как устаревший с версии 17.6.0 и указывает замену \Bitrix\Catalog\Model\Product::add. Перенос на неё требует собственного варианта примера: у D7 другой объект результата, поэтому механическая замена имени метода недостаточна.
Что проверить на тестовом каталоге
- При корректной настройке созданы товар, предложение, привязка и базовая цена без исключения.
- Неверный идентификатор инфоблока отклоняется до создания товара.
- Отказ добавления предложения не маскируется ошибкой цены.
- Отдельно воспроизведены отказ добавления параметров и отказ установки цены.
- Повторный запуск не допускается как незаметный импорт дубликатов.
У CPrice::SetBasePrice при стандартном значении bGetID=false результат — true или false. Этот метод также устарел с 17.6.0; для новой реализации документация указывает модели Price::add и Price::update.