Добавляем товар в Битрикс правильно

  • Добавляем товар в Битрикс правильно

    Антон Долганин 19 Июня 2015 11:25 17373
    Немного ликбеза. В Битрикс элемент инфоблока отдельно, цена (несколько) отдельно, и сущность товара - отдельно. Что такое товар? Это остаток, закупочная цена, настройки уменьшения остатка, и так далее. В общем, все, кроме цены. Вот тут небольшой совет как его добавлять более оптимально.

    Допустим у нас идет цикл элементов, в котором мы обновляем остатки (как раз товары). Типичный импорт.
    Примерно так:
    $res = CIBlockElement::getList(array(), array('ID', 'CATALOG_QUANTITY'));  
    while ($row = $res->fetch()) { 
        //  
    }


    Как обновить остаток?
    Мы не сможем сделать вот так:
    CCatalogProduct::update($row['ID'], array('QUANTITY' => $fields['QUANTITY']));


    Потому что товара еще может не быть в базе (не смотря на то, что элемент уже есть).

    Мы можем сделать вот так:
    CCatalogProduct::add(array('ID' => $row['ID'], 'QUANTITY' => $fields['QUANTITY']));


    По идее этого достаточно. В последнем случае система добавит товар только если его нет.

    Но я бы улучшил еще вот так обновление остатка:
    if ($row['CATALOG_QUANTITY'] === null || $row['CATALOG_QUANTITY'] === '') {
       CCatalogProduct::add(array('ID' => $row['ID'], 'QUANTITY' => $fields['QUANTITY']), false);
    } elseif ($fields['QUANTITY'] != $row['CATALOG_QUANTITY']) {
       CCatalogProduct::update($row['ID'], array('QUANTITY' => $fields['QUANTITY']));
    }
    


    То есть - идем добавлять товар только если его 100% нет еще в системе. В ином случае обновляем.
Александр
10 Июля 2015 14:14
То есть такой код плох, что мы лезем в базу, но при этом убеждаемся на все 100%, что он там есть?

$dbProduct = CCatalogProduct::GetList( array(),array('ID' => $arElement['ID']) );
if($arProduct = $dbProduct->Fetch()) {
   if(CCatalogProduct::Update($arProduct['ID'], $arProductFields)) {
      file_put_contents($logPaths['price'], "Товар обновлен: " . $arProduct['ID'] . "\n", FILE_APPEND);
   }
   else {
      file_put_contents($logPaths['price'], "!!! Товар не обновлен: " . $arElement['ID'] . "\n", FILE_APPEND);
   }
}
else {
   $arProductFields['ID'] = $arElement['ID'];
   if(CCatalogProduct::Add($arProductFields)) {
      file_put_contents($logPaths['price'], "Добавили параметры товара к элементу каталога: " . $arElement['ID'] . "\n", FILE_APPEND);
   }
   else {
      file_put_contents($logPaths['price'], "!!! Ошибка добавления товара: " . $arElement['ID'] . "\n", FILE_APPEND);
   }
}
 
Антон Долганин
10 Июля 2015 14:28
что мы лезем в базу
В целом да, если товаров много, а импорт вдруг частый.

До публикации я показывал код разработчикам Битрикс - они одобрили подход.
PS: В вашем коде вам надо Add передавать второй параметр false, иначе система еще и сама будет искать товар, дублируя запрос http://bxapi.ru/src/?module_id=catalog&name=CCatalogProduct::Add
Александр
10 Июля 2015 14:38
Большое спасибо, не знал!
Николай
29 Июля 2015 10:41
Дано: проект с 8000 единиц товара, обновление остатков из 1с файлом csv каждые 5 минут.
Товар это 2 инфоблока ТОВАР (типа артикул) - ПРЕДЛОЖЕНИЯ (типа штрихкод)
Решение:
Реализовывали 3 способами. Стандартный API (сайт ложился), Через обращение в db api (сайт ложился).
В итоге добавили поле quantity_new в b_catalog_product
и делаем что-то вроде
LOAD DATA INFILE во временную таблицу
'UPD ATE `b_catalog_product` SE T `QUANTITY_NEW` = из временной таблицы
меняем местами QUANTITY_NEW QUANTITY

Все занимает 4 секунды, сайт не падает.


Знаем, что бд трогать нельзя и события обновления остатков не срабатывают. Мы сильно согрешили?))))) Есть альтернативы?!)
Антон Долганин
29 Июля 2015 20:34
Да в целом вполне рабочее решение (Битрикс конечно официально против такого :) ).

Я бы даже и на заметку взял. Спасибо.  
rardAbose
24 Октября 2019 1:36
hi :) bross :)