Как создать свойство инфоблока в Битрикс через CIBlockProperty::Add?

На практике миграция отработала без ошибок, в админке свойство 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, а не админка

Сравнение: админка и программный 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 и когда он нужен

Workflow CIBlockProperty::Add: поля и возврат ID

CIBlockProperty::Add регистрирует новое свойство в таблицах модуля iblock и возвращает числовой ID свойства. Минимальный набор полей: IBLOCK_ID (номер инфоблока), NAME (подпись в админке), CODE (латиница, уникален внутри инфоблока), PROPERTY_TYPE (буква типа: S, N, L и др.).

Нужен Add, когда поле должно появиться до массовой загрузки элементов. Не нужен, если свойство уже есть и вы только меняете значение у товара - тогда PROPERTY_VALUES в Element::Add или SetPropertyValuesEx.

Выполните минимальный Add: модуль, поля и LAST_ERROR

Чеклист минимального Add с обработкой LAST_ERROR
  1. Модуль: Loader::includeModule('iblock') или CModule::IncludeModule('iblock').
  2. Идемпотентность: CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId, 'CODE' => 'COLOR']) - если запись есть, сохраните ID и не вызывайте Add.
  3. Объект: $ibp = new CIBlockProperty;
  4. Поля и вызов: 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 → сброс кеша фасета
  1. CIBlock::Update($iblockId, ['SECTION_PROPERTY' => 'Y']) при необходимости.
  2. $ibp->Update($propId, ['IBLOCK_ID' => $iblockId, 'SMART_FILTER' => 'Y', 'FILTERABLE' => 'Y']).
  3. 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:

  1. Свойство видно в админке инфоблока с нужным CODE и типом.
  2. Повторный запуск миграции не создает дубликат и не падает.
  3. Умный фильтр и карточка показывают поле (если включали флаги).
  4. Тестовый элемент через 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 элемента не создает новые поля инфоблока.

Обсудить вашу задачу

Было полезно?

Поставьте лайк, если статья помогла разобраться.

Поделиться статьёй

Отправьте тому, кому это пригодится.

Telegram ↗ MAX ↗ ВКонтакте ↗ Одноклассники ↗
Все статьи ↗

Как настроить регистрацию и личный кабинет покупателя на 1С-Битрикс?

Структура шаблонов сайта в Битриксе и поиск header footer

Как настроить скидки и промокоды на 1С-Битрикс: правила корзины и купоны