Массовая генерация символьных кодов через API Битрикса средствами старого ядра и D7

Задача. Простановка символьных кодов у всех элементов инфоблока (или его конкретного раздела) через API Битрикса средствами старого ядра и D7.

Массовая простановка символьных кодов в Битриксе

1. Нужно массово (для всех элементов инфоблока или конкретного раздела) выполнить логику:

  • Вариант 1: Если у элемента есть символьный код, то не меняем его, если нет – формируем по новым правилам.
  • Вариант 2: Если у элемента есть код, то заменить его на новый (по тем же правилам).

2. Правило формирования символьного кода из названия берётся из массива $params:


    $params = array(
        "max_len" => "100",            // обрезает символьный код до 100 символов
        "change_case" => "L",         // буквы преобразуются к нижнему регистру
        "replace_space" => "-",       // меняем пробелы на "-"
        "replace_other" => "-",       // все "левые" символы заменяем на "-"
        "delete_repeat_replace" => "true", // удаляем повторяющиеся "-"
        "safe_chars" => "false"       // cтрока символов, которые не нужно заменять (по умолчанию – пустая строка).
    );
    

3. В каждом примере кода обязательно ведётся логирование через AddMessage2Log().


Решение

Ниже — статья, где мы рассматриваем 4 примера массовых операций (по два на каждое ядро):

  • Старое ядро (CIBlockElement)
    1. Если код у элемента уже есть, не меняем его. Если нет кода — создаём по заданным правилам.
    2. Если код есть — заменяем его по новым правилам.
  • Новая модель (D7)
    1. Если код у элемента есть — не меняем. Если нет кода — генерируем по заданным правилам.
    2. Если код есть — заменяем его по новым правилам.

1. Старое ядро (CIBlockElement)

Пример 1. Если код у элемента уже есть, не меняем его. Если нет кода — создаём по заданным правилам.


    <?php
    AddMessage2Log("Начало массовой обработки элементов (Старое ядро). Вариант 1");

    // Обязательно подключаем модуль
    CModule::IncludeModule("iblock");

    // Указываем ID инфоблока
    $iblockId = 2;

    // Набор параметров для транслитерации
    $params = array(
        "max_len" => "100",
        "change_case" => "L",
        "replace_space" => "-",
        "replace_other" => "-",
        "delete_repeat_replace" => "true",
        "safe_chars" => "false",
    );

    // Получаем все элементы нужного инфоблока
    $arFilter = [
        "IBLOCK_ID" => $iblockId
    ];
    $rsElements = CIBlockElement::GetList([], $arFilter, false, false, ["ID", "NAME", "CODE", "IBLOCK_ID"]);
    while ($arElement = $rsElements->GetNext())
    {
        $elementID = $arElement["ID"];
        $elementName = $arElement["NAME"];
        $elementCode = $arElement["CODE"];

        if (!empty($elementCode))
        {
            // Код уже есть, не меняем
            AddMessage2Log("Элемент ID {$elementID}: символьный код уже существует ({$elementCode}), пропускаем.");
        }
        else
        {
            // Генерируем новый код из имени
            $newCode = Cutil::translit($elementName, "ru", $params);

            // Обновляем элемент
            $el = new CIBlockElement;
            $res = $el->Update($elementID, ["CODE" => $newCode]);
            if ($res)
            {
                AddMessage2Log("Элемент ID {$elementID}: новый код установлен -> {$newCode}");
            }
            else
            {
                AddMessage2Log("Элемент ID {$elementID}: ошибка при обновлении кода -> " . $el->LAST_ERROR);
            }
        }
    }
    ?>
    

В данном скрипте:

  1. Задаём $iblockId, массив $params для формирования кода.
  2. Выбираем все элементы инфоблока.
  3. Для каждого проверяем, есть ли у него код: если есть — пропускаем, если нет — формируем транслитом из NAME.
  4. Всё логируем через AddMessage2Log().

Пример 2. Если код у элемента есть – меняем его по новым правилам


    <?php
    AddMessage2Log("Начало массовой обработки элементов (Старое ядро). Вариант 2");

    // Подключаем модуль
    CModule::IncludeModule("iblock");

    // ID инфоблока
    $iblockId = 2;

    // Параметры для транслита
    $params = array(
        "max_len" => "100",
        "change_case" => "L",
        "replace_space" => "-",
        "replace_other" => "-",
        "delete_repeat_replace" => "true",
        "safe_chars" => "false",
    );

    // Получаем все элементы инфоблока
    $arFilter = [
        "IBLOCK_ID" => $iblockId
    ];
    $rsElements = CIBlockElement::GetList([], $arFilter, false, false, ["ID", "NAME", "CODE", "IBLOCK_ID"]);
    while ($arElement = $rsElements->GetNext())
    {
        $elementID = $arElement["ID"];
        $elementName = $arElement["NAME"];
        $elementCode = $arElement["CODE"];

        // Формируем код по-новому из названия
        $newCode = Cutil::translit($elementName, "ru", $params);

        // Если старый код такой же, как новый, - можем пропустить, но
        // в примере принудительно меняем, чтобы показать механику
        $el = new CIBlockElement;
        $res = $el->Update($elementID, ["CODE" => $newCode]);
        if ($res)
        {
            AddMessage2Log("Элемент ID {$elementID}: код изменён c [{$elementCode}] на [{$newCode}]");
        }
        else
        {
            AddMessage2Log("Элемент ID {$elementID}: ошибка при обновлении кода -> " . $el->LAST_ERROR);
        }
    }
    ?>
    

Этот вариант покажет, как заменить уже существующий код, не проверяя, пустой ли он. При желании можно усложнить логику: проверять, отличается ли новый транслит от старого кода, и обновлять только при необходимости.


2. Новое ядро (D7)

Пример 3. D7. Если код у элемента есть – оставляем, если нет – генерируем


    <?php
    AddMessage2Log("Начало массовой обработки (D7). Вариант 1");

    use Bitrix\Main\Loader;
    use Bitrix\Iblock\Elements\ElementCatalogTable; // Или ваш класс для нужного инфоблока

    Loader::includeModule('iblock');

    // ID инфоблока
    $iblockId = 3;

    // Параметры транслита
    $params = array(
        "max_len" => "100",
        "change_case" => "L",
        "replace_space" => "-",
        "replace_other" => "-",
        "delete_repeat_replace" => "true",
        "safe_chars" => "false",
    );

    // Получаем нужные элементы (пример: по всему инфоблоку)
    $elements = ElementCatalogTable::getList([
        'filter' => ['IBLOCK_ID' => $iblockId],
        'select' => ['ID', 'NAME', 'CODE']
    ]);

    while ($element = $elements->fetch())
    {
        $elementID = $element['ID'];
        $elementName = $element['NAME'];
        $elementCode = $element['CODE'];

        if (!empty($elementCode))
        {
            // Код существует, не меняем
            AddMessage2Log("D7. Элемент ID {$elementID}: код уже есть ({$elementCode}), пропускаем.");
        }
        else
        {
            // Генерируем новый код
            $newCode = Cutil::translit($elementName, "ru", $params);

            // Обновляем
            $result = ElementCatalogTable::update($elementID, ['CODE' => $newCode]);
            if ($result->isSuccess())
            {
                AddMessage2Log("D7. Элемент ID {$elementID}: установлен новый код -> {$newCode}");
            }
            else
            {
                AddMessage2Log("D7. Элемент ID {$elementID}: ошибка при обновлении -> " . implode(', ', $result->getErrorMessages()));
            }
        }
    }
    ?>
    

В данном примере:

  1. Выбираем все элементы инфоблока 3.
  2. Проверяем CODE: если не пустой, пропускаем, иначе генерируем из NAME.
  3. Обновляем элемент через ORM-метод update() и логируем результат.

Пример 4. D7. Если код у элемента есть – заменяем на новый


    <?php
    AddMessage2Log("Начало массовой обработки (D7). Вариант 2");

    use Bitrix\Main\Loader;
    use Bitrix\Iblock\Elements\ElementCatalogTable; // Замените на свой класс

    Loader::includeModule('iblock');

    // ID инфоблока
    $iblockId = 3;

    // Параметры транслита
    $params = array(
        "max_len" => "100",
        "change_case" => "L",
        "replace_space" => "-",
        "replace_other" => "-",
        "delete_repeat_replace" => "true",
        "safe_chars" => "false",
    );

    $elements = ElementCatalogTable::getList([
        'filter' => ['IBLOCK_ID' => $iblockId],
        'select' => ['ID', 'NAME', 'CODE']
    ]);

    while ($element = $elements->fetch())
    {
        $elementID = $element['ID'];
        $oldCode   = $element['CODE'];
        $elementName = $element['NAME'];

        // Формируем новый код на основе имени
        $newCode = Cutil::translit($elementName, "ru", $params);

        // Меняем код
        $result = ElementCatalogTable::update($elementID, ['CODE' => $newCode]);
        if ($result->isSuccess())
        {
            AddMessage2Log("D7. Элемент ID {$elementID}: код изменён с [{$oldCode}] на [{$newCode}]");
        }
        else
        {
            AddMessage2Log("D7. Элемент ID {$elementID}: ошибка при обновлении -> " . implode(', ', $result->getErrorMessages()));
        }
    }
    ?>
    

Таким образом, мы обновляем уже существующие коды, даже если они были заданы ранее.


Дополнения и советы

  1. Фильтр по разделам: Если нужно обрабатывать только элементы конкретного раздела (с учётом вложенных), в фильтре указывайте:
    
                'filter' => [
                    'IBLOCK_ID' => $iblockId,
                    'SECTION_ID' => $sectionId,
                    'INCLUDE_SUBSECTIONS' => 'Y'
                ]
                
    Аналогично и в D7-методе. Либо используйте зависимость от структуры вашего ORM-класса.
  2. Оптимизация: При большом объёме элементов (тысячи и десятки тысяч) используйте постраничную выборку (параметры limit, offset) или batch-обработку. Иначе скрипт может превысить время выполнения.
  3. Уникальность: Если в инфоблоке необходимо, чтобы коды были уникальными, стоит дополнительно проверять конфликты. По умолчанию 1С-Битрикс иногда сам добавляет суффиксы вида -1, -2 и т.д. Но если хотите контролировать это программно, придётся писать дополнительную логику.
  4. Логирование: Функция AddMessage2Log() отлично подходит для отладки. Результаты можно смотреть в /bitrix/logs/ (или другом месте, в зависимости от конфигурации). Для продакшн-среды имеет смысл реализовать более гибкий механизм, если данных очень много, чтобы не раздувать файлы логов.

Итоги

Мы продемонстрировали, как массово обработать символьные коды у элементов целого инфоблока (или его раздела) в 1С-Битрикс:

  • Старое ядро (CIBlockElement) — два примера кода:
    1. Если у элемента код есть, мы не трогаем его, если нет — формируем транслитом из названия.
    2. Если код есть — обновляем по новым правилам (транслитерируем заново).
  • Новое ядро D7 — аналогичные два примера:
    1. Логика «код есть — не меняем».
    2. Логика «всегда обновляем код» (перезаписываем).

Везде задействованы массив $params для CUtil::translit() и функция AddMessage2Log() для журналирования хода выполнения. При необходимости вы легко можете адаптировать эти скрипты под свои нужды: фильтровать нужный инфоблок, нужный раздел, модифицировать или ужесточать правила генерации символьного кода.

Теги:  символьные коды, инфоблоки, API, D7, массовая обработка

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

Лендинг

от 3 дней

от 25 000 рублей

Разработка одностраничного сайта на платформе Битрикс

* стоимость зависит от наличия верстки, использования готового решения и т.д.

Модули и компоненты для «1С-Битрикс»

оценка производится на основе предоставленного Технического Задания

от 20 000 рублей
Разработка дополнительных модулей для 1С-Битрикс, расширение функционала, внедрение любых решений, требующихся для выполнения ваших бизнес-задач.

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

Перенос сайтов на «1С-Битрикс»

сайты на платформе «1С-Битрикс» — это удобство, надежность и высокая посещаемость

от 12 000 рублей
Перенос сайтов с любых CMS и статичных страниц на платформу «1С-Битрикс», с учетом дизайна, верстки и урл-адресов. С сохранением всей информации и структуры сайта.

* зависит от объема выполняемых работ.