Иногда в 1С-Битрикс нужно массово изменить значение свойства у множества элементов инфоблока. Например, обновить код ТН ВЭД у товаров, поменять артикул, проставить новое значение какого-либо справочного свойства.
Через админку это делать долго: открыть каждый товар → изменить свойство → сохранить. Если элементов сотни или тысячи — часы рутины.
В этой заметке — скрипт на D7 API, который делает это за секунды. Он находит все элементы с определённым значением свойства и меняет его на новое.
Задача
- Инфоблок:
ID = 51(например, каталог товаров) - Свойство:
TN_VED(код ТН ВЭД) - Старое значение:
3924900000 - Новое значение:
3924900009
Нужно найти все элементы, у которых свойство TN_VED = 3924900000, и заменить его на 3924900009.
Скрипт
<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementPropertyTable;
use Bitrix\Iblock\PropertyTable;
Loader::includeModule('iblock');
// ==== НАСТРОЙКИ ====
$IBLOCK_ID = 51; // ID инфоблока
$PROPERTY_CODE = 'TN_VED'; // Символьный код свойства
$OLD_VALUE = '3924900000';
$NEW_VALUE = '3924900009';
// ===================
// Получаем ID свойства
$property = PropertyTable::getList([
'filter' => ['=IBLOCK_ID' => $IBLOCK_ID, '=CODE' => $PROPERTY_CODE],
'select' => ['ID', 'MULTIPLE'],
])->fetch();
if (!$property) {
die("Свойство с кодом {$PROPERTY_CODE} не найдено в инфоблоке {$IBLOCK_ID}\n");
}
$propId = (int)$property['ID'];
echo "ID свойства: {$propId}\n";
// Находим все записи со старым значением
$rows = ElementPropertyTable::getList([
'filter' => [
'=IBLOCK_PROPERTY_ID' => $propId,
'=VALUE' => $OLD_VALUE,
],
'select' => ['ID', 'IBLOCK_ELEMENT_ID', 'VALUE'],
]);
$count = 0;
while ($row = $rows->fetch()) {
$res = ElementPropertyTable::update($row['ID'], [
'VALUE' => $NEW_VALUE,
]);
if ($res->isSuccess()) {
$count++;
echo "Обновлён элемент ID={$row['IBLOCK_ELEMENT_ID']} (запись свойства ID={$row['ID']})\n";
} else {
echo "Ошибка для элемента {$row['IBLOCK_ELEMENT_ID']}: "
. implode(', ', $res->getErrorMessages()) . "\n";
}
}
echo "Готово. Обновлено записей: {$count}\n";
Как это работает
1. Подключение пролога
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
Подключает ядро Битрикс без запуска шаблона сайта. Это важно для CLI-скриптов и cron-задач — скрипт работает «в фоне», не рендерит HTML.
2. Подключение модуля iblock
Loader::includeModule('iblock');
Без этой строки классы ElementPropertyTable и PropertyTable не будут доступны.
3. Получение ID свойства по символьному коду
$property = PropertyTable::getList([
'filter' => ['=IBLOCK_ID' => $IBLOCK_ID, '=CODE' => $PROPERTY_CODE],
'select' => ['ID', 'MULTIPLE'],
])->fetch();
В Битриксе значения свойств хранятся не в основной таблице элементов, а в отдельной таблице b_iblock_element_property. Чтобы с ней работать через D7, нужно знать ID свойства — оно уникально для каждого инфоблока.
Мы передаём символьный код (TN_VED), а получаем числовой ID — по нему потом ищем значения.
4. Поиск всех записей со старым значением
$rows = ElementPropertyTable::getList([
'filter' => [
'=IBLOCK_PROPERTY_ID' => $propId,
'=VALUE' => $OLD_VALUE,
],
'select' => ['ID', 'IBLOCK_ELEMENT_ID', 'VALUE'],
]);
ElementPropertyTable — это D7-обёртка над b_iblock_element_property. Каждая строка этой таблицы — одно значение свойства у одного элемента.
Если свойство множественное — у элемента будет несколько строк. Если одиночное — одна.
Мы фильтруем по ID свойства и по значению — это находит все нужные записи.
5. Обновление значений
while ($row = $rows->fetch()) {
$res = ElementPropertyTable::update($row['ID'], [
'VALUE' => $NEW_VALUE,
]);
// ...
}
Обновляем каждую запись по её ID — меняем VALUE на новое.
Важно: мы обновляем не элемент, а запись свойства. Это безопаснее — не затрагивает другие поля элемента, не сбрасывает кэш страницы.
6. Подсчёт и вывод
В конце — сколько записей обновлено. Если что-то упало — видно, у какого элемента ошибка и почему.
Где запускать
Вариант 1 — разово через браузер
- Создайте файл
update_property.phpв корне сайта - Откройте
https://ваш-сайт.ru/update_property.php - Дождитесь выполнения
- Удалите файл — иначе любой желающий сможет его запустить
⚠️ Для продакшена — не лучший вариант. Файл может попасть в индексы, в логи, стать дырой.
Вариант 2 — через CLI (рекомендую)
php -f /path/to/site/update_property.php
Плюсы:
- Не доступен из браузера
- Работает в фоне
- Можно повесить на cron
- Логи удобно писать в файл
Вариант 3 — через агента / cron
Оберните код в агент Битрикс и запускайте раз в сутки:
\CAgent::AddAgent(
'updateTnVedAgent();',
'main',
'N',
86400, // раз в сутки
'',
'Y',
date('d.m.Y H:i:s', strtotime('+1 day'))
);
function updateTnVedAgent() {
// ... код скрипта ...
return 'updateTnVedAgent();'; // перезапустить через сутки
}
Подводные камни
1. Множественные свойства
Если свойство множественное, у элемента может быть несколько записей с одинаковым значением. Скрипт обновит все — это обычно то, что нужно. Но проверяйте логику: иногда нужно менять только «первую» или «последнюю».
2. Кэш
После обновления значений через ElementPropertyTable кэш компонентов и страниц не сбрасывается. Если сайт показывает старое значение — очистите кэш:
- В админке: Настройки → Автокеширование → Очистить весь кэш
- Или через CLI:
php -f bitrix/modules/main/tools/clear_cache.php
3. Права и роли
Скрипт работает от имени того, кто его запускает. Если запускаете через браузер — от текущего пользователя. Для CLI — от пользователя, под которым запущен PHP. Убедитесь, что у него есть права на изменение инфоблока.
4. Транзакции
Скрипт не оборачивает изменения в транзакцию. Если упадёт на середине — часть записей обновится, часть нет. Для больших объёмов лучше:
- Разбить на батчи (по 500 элементов)
- Обернуть в
Application::getConnection()->startTransaction() - Добавить логирование прогресса
5. Производительность
Для больших инфоблоков (10 000+ элементов) скрипт может работать долго. ElementPropertyTable::update делает отдельный SQL-запрос на каждую запись. Если нужно ускорить — можно сгруппировать:
$connection = \Bitrix\Main\Application::getConnection();
$sql = "UPDATE b_iblock_element_property
SET VALUE = '{$NEW_VALUE}'
WHERE IBLOCK_PROPERTY_ID = {$propId}
AND VALUE = '{$OLD_VALUE}'";
$connection->queryExecute($sql);
Но это обходит D7 API — теряются события (OnBeforeIBlockElementUpdate и т.п.). Используйте с осторожностью.
Безопасность
Никогда не запускайте такой скрипт на продакшене без бэкапа.
Перед запуском:
- Сделайте резервную копию БД (или хотя бы таблиц
b_iblock_element_property) - Протестируйте на копии сайта
- Убедитесь, что знаете ID инфоблока и код свойства — ошибка в них может испортить другие данные
- Удалите файл после использования
Итог
D7 API в 1С-Битрикс даёт чистый способ массово обновлять значения свойств инфоблока — без ручной работы в админке. Ключевые моменты:
- Значения свойств хранятся в
b_iblock_element_property— работаем черезElementPropertyTable - Сначала получаем ID свойства по коду через
PropertyTable - Фильтруем по ID свойства и старому значению
- Обновляем каждую запись через
ElementPropertyTable::update - Очищаем кэш после — иначе сайт покажет старое
Скрипт универсален — меняйте IBLOCK_ID, PROPERTY_CODE, OLD_VALUE, NEW_VALUE под свою задачу.