Настройка массового перемещения товаров между разделами 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Настройка массового перемещения товаров между разделами 1С-Битрикс
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1181
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    813
  • 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С-Битрикс

Реструктуризация каталога: раздел «Смартфоны» разбивается на «Смартфоны Apple», «Смартфоны Samsung», «Смартфоны Xiaomi». 800 товаров нужно распределить по новым разделам. Или поставщик изменил структуру категорий, и 400 позиций нужно перенести из одного раздела в другой.

Структура разделов и привязка товаров

Разделы инфоблока хранятся в b_iblock_section. Привязка элемента к разделу — поле IBLOCK_SECTION_ID в b_iblock_element (основной раздел). Дополнительная привязка к нескольким разделам — таблица b_iblock_section_element: IBLOCK_ELEMENT_ID, IBLOCK_SECTION_ID, ADDITIONAL_PROPERTY_ID.

При перемещении товара нужно обновить оба места:

  1. IBLOCK_SECTION_ID в b_iblock_element — основной раздел.
  2. Запись в b_iblock_section_element — для корректной работы фильтров.

Перемещение через CIBlockElement::Update

Стандартный метод обновления с изменением раздела:

\CIBlockElement::Update($elementId, false, [
    'IBLOCK_SECTION_ID' => $newSectionId,
]);

После Update() Битрикс автоматически обновляет b_iblock_section_element. Но метод медленный при массовом применении — каждый вызов проходит через события, кэш, права доступа.

Прямое SQL-обновление для скорости:

global $DB;

$elementIds = implode(',', array_map('intval', $productIds));
$newSection  = (int)$newSectionId;

$DB->Query("
    UPDATE b_iblock_element
    SET IBLOCK_SECTION_ID = {$newSection}
    WHERE ID IN ({$elementIds})
");

$DB->Query("
    DELETE FROM b_iblock_section_element
    WHERE IBLOCK_ELEMENT_ID IN ({$elementIds})
    AND ADDITIONAL_PROPERTY_ID IS NULL
");

foreach ($productIds as $id) {
    $DB->Query("
        INSERT INTO b_iblock_section_element
            (IBLOCK_ELEMENT_ID, IBLOCK_SECTION_ID)
        VALUES
            ({$id}, {$newSection})
    ");
}

Прямой SQL работает в 50-100 раз быстрее CIBlockElement::Update() для массовых операций, но требует ручного сброса кэша.

Многораздельная привязка

Если товар должен отображаться в нескольких разделах одновременно (например, «Смартфоны» и «Акции»), в b_iblock_section_element добавляется несколько строк для одного IBLOCK_ELEMENT_ID:

// Удалить старые привязки к разделам
\Bitrix\Iblock\SectionElementTable::deleteByFilter([
    'IBLOCK_ELEMENT_ID' => $elementId,
    'ADDITIONAL_PROPERTY_ID' => false,
]);

// Добавить новые
foreach ($sectionIds as $secId) {
    \Bitrix\Iblock\SectionElementTable::add([
        'IBLOCK_ELEMENT_ID' => $elementId,
        'IBLOCK_SECTION_ID' => $secId,
    ]);
}

Основной раздел (IBLOCK_SECTION_ID в b_iblock_element) при этом остаётся один — тот, который считается «главным» для хлебных крошек и URL.

Сброс кэша после перемещения

После массового перемещения кэш компонентов каталога протухает не сразу. Принудительный сброс:

\Bitrix\Main\Application::getInstance()->getTaggedCache()->clearByTag('iblock_id_' . $iblockId);

// Для конкретных разделов
foreach (array_unique(array_merge($oldSectionIds, [$newSectionId])) as $secId) {
    \Bitrix\Main\Application::getInstance()->getTaggedCache()
        ->clearByTag('iblock_section_' . $secId);
}

Перемещение по условию

Для автоматического распределения товаров по разделам на основе свойств — например, по бренду:

$brandSectionMap = [
    'Apple'   => 125,
    'Samsung' => 126,
    'Xiaomi'  => 127,
];

$res = \CIBlockElement::GetList(
    [],
    ['IBLOCK_ID' => $iblockId, 'IBLOCK_SECTION_ID' => $sourceSection],
    false,
    false,
    ['ID', 'PROPERTY_BRAND']
);

while ($item = $res->GetNext()) {
    $brand    = $item['PROPERTY_BRAND_VALUE'];
    $targetId = $brandSectionMap[$brand] ?? null;
    if ($targetId) {
        \CIBlockElement::Update($item['ID'], false, ['IBLOCK_SECTION_ID' => $targetId]);
    }
}

При больших объёмах этот скрипт запускается через агент Битрикса пакетами по 100-200 элементов с сохранением прогресса в b_option.