На практике миграция отработала без ошибок, в админке свойство COLOR на месте, а на витрине умный фильтр пустой. Частая причина: CIBlockProperty::Add создал только схему поля, а SMART_FILTER и SECTION_PROPERTY не включили, плюс путают Add свойства с PROPERTY_VALUES при создании товара. Ниже - идемпотентный Add с проверкой CODE, decision-tree по PROPERTY_TYPE, связка с enum (B88) и тест записи через CIBlockElement::Add (B90).
CIBlockProperty::Add в 1С-Битрикс: Управление сайтом - legacy-метод класса CIBlockProperty, который создает описание свойства на уровне инфоблока (поля IBLOCK_ID, NAME, CODE, PROPERTY_TYPE и опционально VALUES, USER_TYPE, SMART_FILTER). Возвращает ID свойства или false; текст ошибки - в LAST_ERROR. Не записывает значения элементов - для этого CIBlockElement::Add / SetPropertyValuesEx (B90). Сегодня: проверьте CODE через GetList, задайте тип, включите фильтр с SECTION_PROPERTY=Y и прогоните миграцию повторно.
Речь про 1С-Битрикс: Управление сайтом (CMS), не про Bitrix24 CRM. Свойство инфоблока - это "колонка" каталога: цвет, артикул, бренд. Создать сам инфоблок в админке - гайд по инфоблокам. Настроить витрину и фильтр руками - свойства каталога в админке; здесь фокус на программном Add для деплоя и импорта.
Разберите, когда нужен CIBlockProperty::Add, а не админка
CIBlockProperty::Add добавляет новое поле в структуру инфоблока: как если бы вы нажали "Добавить свойство" в настройках, но из PHP-скрипта. Это нужно в миграциях (Sprint Migration), при переносе каталога между стендами, в CI/CD, когда один и тот же CODE должен появиться на dev и prod без ручного клика.
| Ситуация | Админка (B53) | CIBlockProperty::Add |
|---|---|---|
| Одно свойство на тесте | Быстрее | Избыточно |
| Деплой на 3 стенда | Риск рассинхрона | Идемпотентный скрипт |
| Импорт каталога из 1С | Не масштабируется | Add до записи товаров |
| Повторный прогон миграции | Дубликаты вручную | GetList по CODE, skip |
Делайте: Add для автоматизации и версионируемых миграций. Не делайте: Add вместо CIBlockElement::Add - методы про разное: Add свойства = схема, Add элемента = запись значения в карточку.
Что такое CIBlockProperty::Add и когда он нужен
CIBlockProperty::Add регистрирует новое свойство в таблицах модуля iblock и возвращает числовой ID свойства. Минимальный набор полей: IBLOCK_ID (номер инфоблока), NAME (подпись в админке), CODE (латиница, уникален внутри инфоблока), PROPERTY_TYPE (буква типа: S, N, L и др.).
Нужен Add, когда поле должно появиться до массовой загрузки элементов. Не нужен, если свойство уже есть и вы только меняете значение у товара - тогда PROPERTY_VALUES в Element::Add или SetPropertyValuesEx.
Выполните минимальный Add: модуль, поля и LAST_ERROR
- Модуль:
Loader::includeModule('iblock')илиCModule::IncludeModule('iblock'). - Идемпотентность:
CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId, 'CODE' => 'COLOR'])- если запись есть, сохраните ID и не вызывайте Add. - Объект:
$ibp = new CIBlockProperty; - Поля и вызов: IBLOCK_ID, NAME, CODE, PROPERTY_TYPE (например S - строка);
$propId = $ibp->Add($arFields);- при false сразу читайте$ibp->LAST_ERRORили$ibp->getLastError().
<?php
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
$iblockId = 7;
$code = 'COLOR';
$exists = CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId, 'CODE' => $code])->Fetch();
if ($exists) {
$propId = (int)$exists['ID'];
} else {
$ibp = new CIBlockProperty;
$propId = $ibp->Add([
'IBLOCK_ID' => $iblockId,
'NAME' => 'Цвет',
'CODE' => $code,
'PROPERTY_TYPE' => 'S',
'ACTIVE' => 'Y',
]);
if (!$propId) {
throw new \RuntimeException($ibp->LAST_ERROR);
}
}
Типичная ошибка на стейдже: LAST_ERROR «Символьный код уже используется» (дубликат CODE), «Неверный IBLOCK_ID» или несовместимый PROPERTY_TYPE. Без GetList повторный прогон миграции падает на втором Add.
Делайте: бросайте исключение с LAST_ERROR в миграции. Не делайте: игнорировать false - свойство может не создаться, а скрипт пойдет дальше.
Выберите PROPERTY_TYPE и USER_TYPE по decision-tree
PROPERTY_TYPE - одна буква, задающая базовый тип хранения. USER_TYPE - дополнительный обработчик (дата, HTML, справочник directory).
| PROPERTY_TYPE | Что хранит | Когда выбрать |
|---|---|---|
| S | Строка | Артикул, текст, с USER_TYPE DateTime или HTML |
| N | Число | Цена, вес, сортировка по числу |
| L | Список (enum) | Фиксированные варианты: цвет, размер |
| F | Файл | PDF, сертификат, доп. фото |
| E | Привязка к элементу | Связанный товар, аксессуар |
| G | Привязка к разделу | Категория-родитель в свойстве |
Для highload - USER_TYPE directory; для даты - DateTime. В список L без enum ID импорт сломается.
Делайте: сверяйте тип с тем, что ждет обмен и умный фильтр. Не делайте: менять PROPERTY_TYPE у существующего свойства с данными - лучше новый CODE.
Настройте список (L): VALUES в Add или enum через B88
Для PROPERTY_TYPE=L варианты можно передать сразу в ключе VALUES при Add:
'PROPERTY_TYPE' => 'L',
'VALUES' => [
['VALUE' => 'Красный', 'DEF' => 'N', 'SORT' => 100],
['VALUE' => 'Синий', 'DEF' => 'N', 'SORT' => 200],
],
Дозапись вариантов и enum ID для импорта - CIBlockPropertyEnum::Add (B88). VALUES - при создании; Enum::Add - при синхронизации стендов.
Делайте: сохраняйте enum ID в конфиге импорта. Не делайте: передавать текст "Красный" в PROPERTY_VALUES элемента - нужен числовой ID варианта.
Включите свойство в умный фильтр и карточку товара
Ловушка: Update с SMART_FILTER=Y может вернуть успех, но фильтр пустой без SECTION_PROPERTY=Y у инфоблока. В админке SaveAction ставит флаг сам; в Add/Update - вручную.
Цепочка: Add → SECTION_PROPERTY=Y → Update SMART_FILTER=Y (с IBLOCK_ID) → CIBlockSectionPropertyLink::Add → сброс кеша фасета
CIBlock::Update($iblockId, ['SECTION_PROPERTY' => 'Y'])при необходимости.$ibp->Update($propId, ['IBLOCK_ID' => $iblockId, 'SMART_FILTER' => 'Y', 'FILTERABLE' => 'Y']).- DETAIL_PAGE_SHOW=Y для карточки; CIBlockSectionPropertyLink::Add для секций.
Настройка фильтра в UI - гайд B53. Без SMART_FILTER витрина поле не покажет.
Делайте: проверяйте фильтр на стейдже после миграции. Не делайте: Update SMART_FILTER без IBLOCK_ID в массиве - поле может не обновиться.
Правьте свойство через Update и повесьте OnBeforeIBlockPropertyAdd
Update после Add: SORT, NAME, флаги. IBLOCK_ID в arFields Update обязателен.
OnBeforeIBlockPropertyAdd - отмена Add или нормализация CODE до вставки. OnAfterIBlockPropertyAdd - лог ID в миграции.
Делайте: централизуйте валидацию CODE в одном обработчике на проекте. Не делайте: дублировать бизнес-правила в каждой миграции без события.
Проверьте результат: админка, повторный прогон, тест B90
Финальный чек-лист перед merge в main:
- Свойство видно в админке инфоблока с нужным CODE и типом.
- Повторный запуск миграции не создает дубликат и не падает.
- Умный фильтр и карточка показывают поле (если включали флаги).
- Тестовый элемент через CIBlockElement::Add с PROPERTY_VALUES записывает значение; пересоздайте фасетный индекс после смены фильтруемых свойств.
Зафиксируйте PROPERTY_ID в down() миграции. Вопросы по цепочке - напишите.
Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: CIBlockProperty::Add, CIBlockProperty::Update, работа с инфоблоками через API.
Частые вопросы
Какие поля обязательны для CIBlockProperty::Add?
Минимум четыре: IBLOCK_ID, NAME, CODE и PROPERTY_TYPE. ACTIVE по умолчанию Y. Без CODE Add часто падает или создает свойство, с которым неудобно работать в PROPERTY_VALUES и ORM. Перед Add проверьте CODE через CIBlockProperty::GetList.
Чем CIBlockProperty::Add отличается от CIBlockPropertyEnum::Add?
CIBlockProperty::Add создает само свойство (схему поля). CIBlockPropertyEnum::Add добавляет один вариант в списочное свойство (PROPERTY_TYPE=L). Сначала свойство, потом enum - подробнее в статье про списочные свойства B88.
Как включить свойство в умный фильтр программно?
Убедитесь, что у инфоблока SECTION_PROPERTY=Y. Затем CIBlockProperty::Update с SMART_FILTER=Y и обязательным IBLOCK_ID в arFields. Для секционного каталога добавьте связь CIBlockSectionPropertyLink::Add. Сбросьте кеш компонента catalog.smart.filter.
Почему LAST_ERROR пишет, что символьный код уже используется?
В этом инфоблоке уже есть свойство с таким CODE. Решение: GetList по IBLOCK_ID и CODE перед Add; при существующей записи используйте её ID или Update вместо повторного Add. Не меняйте CODE у свойства с заполненными товарами без миграции данных.
Можно ли создать свойство без админки?
Да, CIBlockProperty::Add полностью заменяет ручное создание для CMS: результат в той же таблице b_iblock_property. Админка и API эквивалентны по данным; API нужен для миграций, импорта и CI/CD.
Как связать Add свойства с PROPERTY_VALUES при создании элемента?
Порядок строгий: сначала CIBlockProperty::Add (или убедитесь, что свойство есть), для списка получите enum ID через B88, затем в CIBlockElement::Add передайте PROPERTY_VALUES с CODE или ID свойства. Add элемента не создает новые поля инфоблока.
Было полезно?
Поставьте лайк, если статья помогла разобраться.
Поделиться статьёй
Отправьте тому, кому это пригодится.
Можно поделиться и фрагментом: выделите текст статьи.