Как быстро перенести много товаров из одного раздела в другой в 1С-Битрикс при помощи API

В современном интернет-магазине на 1С-Битрикс нередко возникает задача массового редактирования товаров. Одна из самых востребованных операций — перенос группы товаров из одного раздела в другой. Делать это вручную через административную панель может быть утомительно, особенно если речь идет о сотнях или тысячах позиций. К счастью, в 1С-Битрикс существует удобный API для работы с элементами инфоблока, который позволяет автоматизировать процесс.

Как быстро перенести много товаров из одного раздела в другой в 1С-Битрикс при помощи API

В данной статье мы разберемся, как организовать массовый перенос товаров из одного раздела в другой, используя язык PHP и классы 1С-Битрикс, а также рассмотрим несколько вариантов решения этой задачи и полезные примеры кода.

1. Общие принципы использования API инфоблоков

Модуль iblock

Все операции с элементами (товарами) и разделами в 1С-Битрикс проводятся через модуль iblock. Прежде чем использовать классы для работы с инфоблоками, необходимо подключить этот модуль:

CModule::IncludeModule("iblock");

Классы CIBlockElement и CIBlockSection

  • CIBlockElement: отвечает за работу с элементами инфоблоков.
  • CIBlockSection: отвечает за работу с разделами (категориями).

Для решения задачи переноса товаров нужен именно CIBlockElement: через его методы можно изменять данные элементов, в том числе и привязку к разделам.

2. Простой скрипт для массового переноса товаров

Ниже приведен базовый пример PHP-скрипта, который выполнит массовый перенос товаров из одного раздела в другой. Предположим, у нас есть:

  • ID инфоблока: 2 (здесь хранятся товары);
  • ID раздела-источника: 10 (старый раздел);
  • ID нового раздела: 20 (куда нужно перенести).

Важный момент: В 1С-Битрикс товары — это элементы инфоблока, а разделы — это секции инфоблока.

Код скрипта

<?php
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");
CModule::IncludeModule("iblock");

// ID инфоблока (где находятся товары)
$IBLOCK_ID = 2;

// Старый раздел
$OLD_SECTION_ID = 10;

// Новый раздел
$NEW_SECTION_ID = 20;

// Формируем фильтр для выбора нужных товаров
$arFilter = [
    'IBLOCK_ID'           => $IBLOCK_ID,
    'SECTION_ID'          => $OLD_SECTION_ID,
    'INCLUDE_SUBSECTIONS' => 'N', // 'Y' если нужно учесть вложенные подразделы
];

$rsElements = CIBlockElement::GetList([], $arFilter, false, false, ["ID", "IBLOCK_ID"]);
$el = new CIBlockElement;

while ($arElement = $rsElements->Fetch()) {
    // Способ 1. Указать один новый раздел (заменить старую привязку).
    $arFields = [
        "IBLOCK_SECTION_ID" => $NEW_SECTION_ID
    ];

    $result = $el->Update($arElement["ID"], $arFields);
    if ($result) {
        echo "Товар c ID=" . $arElement["ID"] . " перенесен в раздел " . $NEW_SECTION_ID . "<br>";
    } else {
        global $APPLICATION;
        echo "Ошибка при переносе товара ID=" . $arElement["ID"] . ": " . $el->LAST_ERROR . "<br>";
    }
}

Пояснения:

  1. Подключение пролога
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");

Это стандартная практика для скриптов вне административной части. Он загружает ядро Битрикс, подключает нужные классы, функции и т. д.

  1. Подключение модуля
CModule::IncludeModule("iblock");

Без этого модуля мы не сможем использовать классы CIBlockElement и CIBlockSection.

  1. Фильтр $arFilter
  • IBLOCK_ID — инфоблок, где хранятся товары.
  • SECTION_ID — конкретный раздел, из которого мы хотим забрать товары для переноса.
  • INCLUDE_SUBSECTIONS — указывает, нужно ли выбирать товары из вложенных подразделов. По умолчанию N.
  1. Метод CIBlockElement::GetList

Принимает следующие параметры:

  • [] — порядок сортировки (не задан, можно указать ["SORT" => "ASC"] и т. п.).
  • $arFilter — фильтр отбора элементов.
  • false, false — группировку и настройки постраничной навигации.
  • ["ID", "IBLOCK_ID"] — список возвращаемых полей.
  1. Метод Update
$el->Update($arElement["ID"], $arFields);

Позволяет изменить поля элемента. В частности, "IBLOCK_SECTION_ID" => $NEW_SECTION_ID полностью заменяет раздел на новый, убирая привязку к старому.

  1. Сообщения об ошибках
  • $el->LAST_ERROR содержит текст ошибки, если Update не выполнился.

3. Привязка к нескольким разделам

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

CIBlockElement::SetElementSection($ID, $arrSectionIds);

Например, если нужно привязать элемент к разделам с ID = 20 и ID = 21, а также оставить его в текущем:

$arSections = [10, 20, 21]; // перечень всех разделов, где должен лежать товар
CIBlockElement::SetElementSection($arElement["ID"], $arSections);

При этом старые связи с разделами будут полностью переписаны тем списком, что вы передаете во второй параметр. Если ваша задача — лишь добавить дополнительный раздел, сначала нужно получить текущие привязки элемента (через CIBlockElement::GetElementGroups), а затем объединить массивы, чтобы не потерять предыдущие.

4. Использование включения подразделов

Если нужно переносить не только товары из указанного раздела, но и из всех вложенных подразделов, достаточно установить:

'INCLUDE_SUBSECTIONS' => 'Y',

Пример кода

$arFilter = [
    'IBLOCK_ID'           => $IBLOCK_ID,
    'SECTION_ID'          => $OLD_SECTION_ID,
    'INCLUDE_SUBSECTIONS' => 'Y',
];

В этом случае выборка получит товары как из раздела с ID = 10, так и из всех его дочерних категорий.

5. Дополнительные рекомендации и примеры

5.1 Массовое редактирование через административную панель

Иногда не хочется прибегать к написанию кода, если количество товаров не слишком велико. Для этого можно воспользоваться стандартным массовым редактированием:

  1. Зайти в административную часть.
  2. Отфильтровать элементы по разделу.
  3. Отметить галочками нужные позиции.
  4. Внизу выбрать «Изменить» (или «Выбрать действие» → «Изменить»).
  5. На странице массового редактирования проставить нужный раздел и сохранить.

Однако при большом количестве товаров (сотни, тысячи) такой метод все равно не самый удобный — приходится разбивать на страницы по 50–100 элементов. А при регулярном повторении задач по переносу товаров лучше автоматизировать процесс.

5.2 CSV/XML-импорт/экспорт

  • Экспорт в CSV/XML

Вы можете выгрузить список нужных товаров, внести правки в таблице (например, указать новые ID разделов) и импортировать обратно.

  • Плюсы: стандартные механизмы, интерфейс, возможность правки данных «офлайн».
  • Минусы: занимает больше времени, чем простой PHP-скрипт, особенно если нужно делать массовые перенесения регулярно.

5.3 Пошаговая обработка больших массивов товаров

Если у вас очень много товаров (например, десятки тысяч), в одном цикле может произойти превышение по времени выполнения (time limit) или по памяти. Тогда можно сделать пошаговую обработку:

  1. Выполнять выборку не всех элементов сразу, а порциями по 500 или 1000 (с помощью параметров array("nPageSize"=>500) в методе GetList).
  2. После обновления каждой порции выводить сообщение («Обработано 500 товаров») и перезагружать страницу/скрипт (или использовать while-цикл в консоли, если скрипт запускается командой php myscript.php).
  3. Переключаться на следующий «лист» (страницу) выборки, пока не будут обработаны все товары.

6. Полноценный пример кода с несколькими сценариями

Ниже приведен более развернутый скрипт, который позволяет:

  1. Переносить товары из одного или нескольких разделов в новый.
  2. Учитывать или не учитывать вложенные подразделы.
  3. Привязывать к одному или нескольким разделам.
  4. Выводить подробные логи в процессе работы.
<?php
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");
CModule::IncludeModule("iblock");

/*
 * Пример универсального скрипта для переноса/дополнения привязки товаров к разделам
 */

// Данные для настройки
$IBLOCK_ID         = 2;   // ID инфоблока, где лежат товары
$OLD_SECTION_IDS   = [10]; // Массив старых разделов (можно указать несколько)
$NEW_SECTIONS      = [20]; // Список разделов, куда нужно привязать товар
$INCLUDE_SUBSECTIONS = 'N'; // Учитывать вложенные разделы или нет

// Формируем фильтр
$arFilter = [
    'IBLOCK_ID'           => $IBLOCK_ID,
    'SECTION_ID'          => $OLD_SECTION_IDS,
    'INCLUDE_SUBSECTIONS' => $INCLUDE_SUBSECTIONS,
];

// Получаем список элементов
$rsElements = CIBlockElement::GetList([], $arFilter, false, false, ["ID", "IBLOCK_ID"]);
$el = new CIBlockElement;

// Счетчики
$countAll = 0;
$countSuccess = 0;
$countError = 0;

while ($arElement = $rsElements->Fetch()) {
    $countAll++;

    // Пример: перенос с заменой старого раздела
    // $arFields = [
    //     "IBLOCK_SECTION_ID" => reset($NEW_SECTIONS), // берем первый из массива
    // ];
    // $result = $el->Update($arElement["ID"], $arFields);

    // Пример: привязка к нескольким разделам (заменяет все старые привязки)
    $result = CIBlockElement::SetElementSection($arElement["ID"], $NEW_SECTIONS);

    if ($result) {
        $countSuccess++;
        echo "Товар c ID=" . $arElement["ID"] . " успешно обновлен.<br>";
    } else {
        $countError++;
        global $APPLICATION;
        // Если использовали Update()
        // echo "Ошибка при переносе товара ID=" . $arElement["ID"] . ": " . $el->LAST_ERROR . "<br>";

        // Если использовали SetElementSection()
        // Здесь не всегда будет подробное сообщение об ошибке,
        // поэтому в случае неудачи отладить можно,
        // проверив логи или сделав дополнительную проверку прав etc.
        echo "Ошибка при переносе товара ID=" . $arElement["ID"] . "<br>";
    }
}

echo "<hr>";
echo "Всего найдено товаров: $countAll<br>";
echo "Успешно перенесено: $countSuccess<br>";
echo "Ошибок: $countError<br>";

7. Заключение

Массовый перенос товаров в 1С-Битрикс из одного раздела в другой не требует ручного редактирования каждой карточки. Достаточно написать и запустить короткий PHP-скрипт, который опирается на стандартные классы модуля iblock.

Основные преимущества подхода через API:

  1. Гибкость: можно менять не только раздел, но и любые другие поля (название, цены, свойства и т. д.).
  2. Автоматизация: сэкономит массу времени, особенно если приходится регулярно корректировать структуру каталога.
  3. Контроль: вы сами определяете, какие товары переносить (через фильтры).

При правильной настройке скрипта и разумном фильтре (SECTION_ID, INCLUDE_SUBSECTIONS, и т. п.) можно решить большинство типовых задач по обновлению структуры каталога без больших трудозатрат. Если же объем данных огромен, возможно, потребуется дополнительная оптимизация: разбивка на порции, обновление поисковых индексов после переноса и т. д.

Используйте эти примеры кода в своих проектах и дорабатывайте их под конкретные бизнес-требования. Если что-то не работает или появляется ошибка — проверяйте логи, а также убедитесь, что у скрипта есть достаточно прав для изменения элементов (важно в случае сложной структуры групп доступа) и что нет конфликта с другими модулями или настройками сайта.

Успешной разработки!

Теги:  API, массовый перенос товаров, PHP, инфоблоки, разделы, автоматизация

Стоимость услуг по разработке и сопровождению сайтов на 1C-Битрикс

Аутсорсинг

готов помочь, если нет времени

договорная

Могу взять на себя работы по full-stack на основе готовой верстки

* если нет верстки, то возможность верстать с Figma в режиме редактора

Лечение сайтов от вирусов

восстановление сайта и подъем версии PHP

от 25 000 рублей
Лечение сайтов на решениях АСПРО и прочих.

* полный комплекс лечения проекта и закрытия дыр

Техническая поддержка

выполняется с сайтами на основе любых CMS

от 5 000 рублей
Оптимизация производительности действующих интернет-проектов, наполнение и сопровождение, полная техническая поддержка и продвижение в поисковых сетях.

* стоимость зависит от объема и сложности выполняемых работ, используемой CMS.