Важное замечание: D7 ORM не предназначен для создания инфоблоков и свойств
Согласно документации 1С-Битрикс, для инфраструктурных задач (создание инфоблоков, свойств, управление правами) необходимо использовать классическое API. D7 ORM предназначен для повседневной работы с данными (чтение/запись элементов и их значений), а не для создания структуры.
Кроме того, для инфоблоков версии 2.0 методы PropertyTable::add(), PropertyTable::update() и PropertyTable::delete() не работают — управлять свойствами можно только через классическое API.
Правильный подход: классическое API + D7 ORM
Вот полный пример, как создать инфоблок и 10 000 свойств, с учётом всех ограничений:
Шаг 1. Создаём тип инфоблока (классическое API)
<?php
\Bitrix\Main\Loader::includeModule('iblock');
$iblockType = new \CIBlockType;
$result = $iblockType->Add([
'ID' => 'custom_data',
'SECTIONS' => 'N',
'IN_RSS' => 'N',
'LANG' => [
'ru' => [
'NAME' => 'Пользовательские данные',
'SECTION_NAME' => 'Раздел',
'ELEMENT_NAME' => 'Элемент',
],
],
]);
if (!$result) {
throw new \Exception($iblockType->getLastError());
}
Шаг 2. Создаём инфоблок с VERSION = 1 (классическое API)
// VERSION = 1 — обязателен для 10 000 свойств!
$iblock = new \CIBlock;
$iblockId = $iblock->Add([
'IBLOCK_TYPE_ID' => 'custom_data',
'NAME' => 'Таблица с 10000 свойств',
'CODE' => 'table_with_10000_props',
'API_CODE' => 'BigDataTable', // обязательно для D7 ORM
'ACTIVE' => 'Y',
'VERSION' => 1, // версия 1 для > 50 свойств
'LID' => ['s1'],
'GROUP_ID' => [2 => 'R'],
]);
if (!$iblockId) {
throw new \Exception($iblock->getLastError()->getMessage());
}
echo "Создан инфоблок ID: {$iblockId}";
Шаг 3. Создаём 10 000 свойств (классическое API в цикле)
// ВАЖНО: для 10 000 свойств используйте VERSION = 1
// При VERSION = 2 инфоблок создаёт отдельную таблицу
// b_iblock_element_prop_s{ID} с колонками для каждого свойства,
// и у MySQL/PostgreSQL есть лимит на количество колонок (~1017 для InnoDB)
$totalProps = 10000;
$batchSize = 100; // вставка пачками для экономии памяти
for ($i = 1; $i <= $totalProps; $i++) {
$prop = new \CIBlockProperty;
$code = 'PROP_' . str_pad($i, 5, '0', STR_PAD_LEFT); // PROP_00001 .. PROP_10000
$result = $prop->Add([
'IBLOCK_ID' => $iblockId,
'NAME' => "Свойство {$i}",
'CODE' => $code,
'PROPERTY_TYPE' => 'S', // строка — самый экономичный тип
'MULTIPLE' => 'N',
'ACTIVE' => 'Y',
'SORT' => 500,
'FILTRABLE' => 'N',
'SEARCHABLE' => 'N',
]);
if (!$result) {
echo "Ошибка при создании свойства {$i}: "
. $prop->getLastError()->getMessage() . "\n";
}
// Сбрасываем экземпляр для экономии памяти
unset($prop);
// Выводим прогресс каждые 1000 свойств
if ($i % 1000 === 0) {
echo "Создано {$i} свойств...\n";
// Принудительный сброс соединения с БД (для длительных скриптов)
\Bitrix\Main\Application::getConnection()->disconnect();
\Bitrix\Main\Application::getConnection()->connect();
}
}
echo "Готово: создано {$totalProps} свойств.";
Шаг 4. Работа через D7 ORM с готовым инфоблоком
// Компилируем ORM-сущность по API_CODE
$entityClass = \Bitrix\Iblock\IblockTable::compileEntity('BigDataTable');
// Получаем полное имя класса:
// \Bitrix\Iblock\Elements\ElementBigDataTable
// Создаём элемент и заполняем свойства
$element = $entityClass::createObject();
$element->setName('Элемент с 10000 свойств');
for ($i = 1; $i <= 100; $i++) { // заполним первые 100 свойств
$code = 'PROP_' . str_pad($i, 5, '0', STR_PAD_LEFT);
$element->set($code, "Значение для свойства {$i}");
}
$result = $element->save();
echo "Создан элемент ID: " . $result->getId();
Критические ограничения и предупреждения
-
Версия хранения VERSION = 1 обязательна. В документации прямо сказано: версия 2 (отдельная таблица) не рекомендуется, если количество свойств превышает 50. При VERSION = 2 каждое свойство — отдельная колонка в таблице
b_iblock_element_prop_s{IBLOCK_ID}, и MySQL/PostgreSQL имеет жёсткий лимит на число колонок (обычно ~1017 для InnoDB). -
CODE — максимум 50 символов (тип
string(50)в БД). Код должен быть на латинице, не начинаться с цифры, содержать только буквы, цифры и подчёркивание. -
Все 10 000 свойств будут видны в ORM только если у каждого заполнен
CODE. Без кода ORM не видит свойство, и методыget()/set()не работают. -
Производительность: 10 000 вызовов
CIBlockProperty::Add— это 10 000 отдельных SQL-запросов. Скрипт будет работать долго. Рекомендуется запускать его через агенты или из командной строки с увеличеннымmax_execution_time. -
Память: Каждый вызов
CIBlockProperty::Addсоздаёт объект. Для экономии памяти используйтеunset($prop)и периодически сбрасывайте соединение с базой данных. - Альтернатива: Если 10 000 "свойств" — это просто строковые значения, возможно, стоит рассмотреть Highload-блоки (отдельные таблицы ORM) вместо свойств инфоблока. Они гораздо производительнее для такого объёма полей.
Резюме
Через D7 ORM создать инфоблок и его свойства нельзя. Последовательность действий:
- Тип инфоблока —
CIBlockType::Add()(классическое API) - Инфоблок с
VERSION = 1иAPI_CODE—CIBlock::Add()(классическое API) - 10 000 свойств в цикле —
CIBlockProperty::Add()(классическое API) - Работа с элементами и их свойствами — D7 ORM через
IblockTable::compileEntity()