Блог разработчика 1С-Битрикс

Массовая генерация символьных кодов через 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, массовая обработка


Валерий Макеев
05.09.2025 17:24
Этот скрипт массово генерирует символьные коды для всех элементов указанного инфоблока по транслитерации названия, но только у тех элементов, у которых код ещё не задан, используя современное ядро D7 и логируя каждый шаг.
Код
<?php
// Подключаем пролог Битрикс (автоматически подключит ядро и настройки)
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/header.php');

use Bitrix\Main\Loader;
use Bitrix\Iblock\Elements\ElementCatalogTable;

// Логируем начало
AddMessage2Log("Запуск массовой генерации символьных кодов для инфоблока через D7");

// Подключаем модуль инфоблоков
if (!Loader::includeModule('iblock')) {
    AddMessage2Log("Ошибка: не удалось подключить модуль iblock");
    die("Не удалось подключить модуль iblock");
}

// Настройки
$iblockId = 3; // Укажите нужный ID инфоблока
$params = [
    "max_len" => 100,
    "change_case" => "L",
    "replace_space" => "-",
    "replace_other" => "-",
    "delete_repeat_replace" => true,
    "safe_chars" => ""
];

// Получаем элементы без символьного кода
$elements = ElementCatalogTable::getList([
    'filter' => [
        'IBLOCK_ID' => $iblockId,
        'CODE' => false // Только элементы без CODE
    ],
    'select' => ['ID', 'NAME']
]);

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

    // Генерируем символьный код
    $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()));
    }
}

echo "Обработка завершена. Результаты записаны в лог.";
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/footer.php');
?>
Валерий Макеев
05.09.2025 17:26
Ошибка (из предыдущего примера), типа

[Error]
Class "Bitrix\Iblock\Elements\ElementCatalogTable" not found (0)

возникает потому, что класс Bitrix\Iblock\Elements\ElementCatalogTable не существует автоматически — он генерируется только при наличии соответствующего инфоблока, если включена опция "Генерировать коды компонентов" и созданы классы D7 через интерфейс Битрикс (например, через "Типы инфоблоков" → "Генерация D7-классов").

Если таких классов нет — вы не можете использовать ElementCatalogTable, и PHP выбрасывает Class not found.

✅ Можно использовать универсальный D7-метод без зависимостей от сгенерированных классов
Ниже пример, который не требует наличия ElementCatalogTable, а использует стандартный API D7 через CIBlockElement и Bitrix\Iblock\ElementTable:
Код
<?php
// Подключаем пролог Битрикс
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/header.php');

use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
use Bitrix\Main\Entity\DataManager;

// Логируем начало
AddMessage2Log("Запуск массовой генерации символьных кодов для элементов инфоблока (универсальный D7)");

// Подключаем модуль iblock
if (!Loader::includeModule('iblock')) {
    AddMessage2Log("Ошибка: не удалось подключить модуль iblock");
    die("Модуль iblock не подключён");
}

// Настройки
$iblockId = 3; // ← Укажите нужный ID вашего инфоблока
$params = [
    "max_len" => 100,
    "change_case" => "L",           // в нижний регистр
    "replace_space" => "-",         // пробелы на дефис
    "replace_other" => "-",         // прочие символы на дефис
    "delete_repeat_replace" => true, // убрать дубли дефисов
    "safe_chars" => ""              // безопасные символы (если нужны)
];

// Получаем элементы инфоблока без символьного кода
$query = ElementTable::getList([
    'filter' => [
        '=IBLOCK_ID' => $iblockId,
        'CODE' => null // или false — элементы без CODE
    ],
    'select' => ['ID', 'NAME'],
    'limit'  => 5000 // защита от перегрузки; можно запускать по частям
]);

$updatedCount = 0;
while ($element = $query->fetch()) {
    $elementID = $element['ID'];
    $elementName = trim($element['NAME']);

    if (empty($elementName)) {
        AddMessage2Log("D7. Элемент ID {$elementID}: пропущен — пустое название");
        continue;
    }

    // Генерируем символьный код
    $newCode = CUtil::translit($elementName, 'ru', $params);

    // Обновляем поле CODE через ElementTable
    $result = ElementTable::update($elementID, ['CODE' => $newCode]);

    if ($result->isSuccess()) {
        AddMessage2Log("D7. Элемент ID {$elementID}: установлен код '{$newCode}'");
        $updatedCount++;
    } else {
        $errors = implode(', ', $result->getErrorMessages());
        AddMessage2Log("D7. Элемент ID {$elementID}: ошибка обновления -> {$errors}");
    }
}

echo "Готово. Обновлено элементов: {$updatedCount}. Результаты в логах (/bitrix/logs/).";
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/footer.php');
?>

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

Интернет-магазин на готовом решении

от 7 дней

от 40 000 рублей
запуск сайта в максимально короткие сроки

* указана минимальная стоимость. Стоимость выбранной лицензии «1С-Битрикс» оплачивается отдельно.

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

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

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

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

Аутсорсинг

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

договорная

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

* на основе готовой верстки