Архитектура и основные объекты

Highload-блок состоит из описания набора данных, пользовательских полей и записей. Модуль связывает эти слои по идентификатору блока и во время выполнения формирует ORM-объект для работы с записями.

При проектировании полей и переносе структуры разделяйте операции с описанием блока и его записями. Для управления описанием используйте HighloadBlockTable, а для работы с записями — класс данных, который возвращает HighloadBlockTable::compileEntity().

Если способ хранения еще не выбран, сравните Highload-блок, информационный блок и собственный ORM-класс в статье Введение и базовые концепции.

Слои Highload-блока

Описание блока не содержит сами записи. В описании хранятся имя ORM-объекта и название таблицы с записями. Каждое пользовательское поле добавляет записи отдельное свойство и задает его название, тип и настройки.

Описание Highload-блока
├── ID, NAME и TABLE_NAME
├── локализованные названия
├── правила доступа
└── идентификатор пользовательских полей HLBLOCK_<ID>
    └── пользовательские поля UF_*
        └── отдельная таблица записей
            ├── системное поле ID
            ├── одиночные значения
            └── множественные значения и их дополнительное хранилище

Связь между слоями строится вокруг поля ID описания блока:

  • значение HLBLOCK_<ID> объединяет блок с реестром пользовательских полей,

  • значение TABLE_NAME связывает описание с таблицей записей,

  • значение NAME определяет имя динамического ORM-объекта и класса данных,

  • поле HL_ID связывает правило доступа с блоком,

  • пара ID и LID связывает локализованное название с блоком и языком.

Метаданные блока

Класс Bitrix\Highloadblock\HighloadBlockTable управляет описаниями Highload-блоков. Его карта содержит основные поля и вычисляемые связи:

  • ID — автоматически создаваемый целочисленный идентификатор блока,

  • NAME — имя ORM-объекта, которое участвует в имени динамического класса данных,

  • TABLE_NAME — имя отдельной таблицы с записями блока,

  • FIELDS_COUNT — вычисляемое количество пользовательских полей с идентификатором HLBLOCK_<ID>,

  • LANG — ORM-связь с локализованным названием блока для текущего языка.

Класс HighloadBlockTable отвечает не только за строку описания. При добавлении, переименовании таблицы и удалении блока класс синхронизирует метаданные со схемой хранения. Поэтому не изменяйте описание блока и структуру таблиц прямыми запросами к базе данных.

Связанные классы метаданных

Дополнительные классы отделяют локализацию и правила доступа от основного описания.

Класс Bitrix\Highloadblock\

Что делает

Ключевые поля

HighloadBlockLangTable

Хранит название блока для конкретного языка

  • Идентификатор блока ID,
  • идентификатор языка LID длиной до двух символов,
  • локализованное NAME

HighloadBlockRightsTable

Связывает блок, задачу доступа и код субъекта доступа

  • Идентификатор блока HL_ID,
  • идентификатор задачи доступа TASK_ID,
  • код субъекта доступа ACCESS_CODE

HighloadBlock

Содержит данные одного Highload-блока из HighloadBlockTable и позволяет получить класс его записей через getEntityDataClass()

  • Поля карты HighloadBlockTable

При запросах через динамический ORM-класс правила доступа из HighloadBlockRightsTable не применяются автоматически. Перед прямой работой с классом данных приложение должно отдельно проверить, разрешена ли нужная операция. Настройка доступа описана в статье События записей и права доступа.

Пользовательские поля и записи

Каждому Highload-блоку соответствует идентификатор пользовательских полей вида HLBLOCK_<ID>. Например, для блока с идентификатором 7 модуль использует значение HLBLOCK_7. По этому ключу менеджер пользовательских полей получает карту UF_*, которую compileEntity() добавляет к ORM-объекту записей.

Таблица записей появляется вместе с блоком. Сначала она содержит только автоматически создаваемое целочисленное поле ID. При добавлении пользовательского поля модуль добавляет в таблицу колонку с именем поля и типом хранения, который соответствует типу пользовательского поля.

Общие типы и настройки полей описаны в статье Пользовательские поля. Порядок создания и изменения полей Highload-блока приведен в статье Создание, настройка и перенос Highload-блоков.

Одиночные значения

Одиночное пользовательское поле становится скалярным полем ORM-объекта. Значение хранится в колонке основной записи. Настройка MANDATORY определяет признак обязательности поля в динамической ORM-карте.

Тип пользовательского поля определяет PHP-представление, преобразование перед сохранением и дополнительные ORM-связи. Например, тип привязки к элементам Highload-блока может добавить поле-ссылку с окончанием _REF.

Для настройки привязок и служебных полей справочников используйте рекомендации из статьи Связи и справочники на Highload-блоках.

Множественные значения

Для множественного поля модуль создает дополнительное хранилище значений. Каждая строка в нем связывает ID основной записи с одним значением поля. Модуль также поддерживает представление массива в основной записи и синхронизирует оба представления через Bitrix\Highloadblock\DataManager.

В ORM-карте множественное поле доступно как массив. Дополнительное выражение с окончанием _SINGLE позволяет обращаться к отдельным значениям через связь со вспомогательным ORM-объектом.

Не изменяйте основную таблицу и дополнительное хранилище множественного поля независимо. Прямые запросы могут нарушить согласованность представлений. Добавляйте и изменяйте записи через динамический класс данных.

Динамический ORM-объект

Метод HighloadBlockTable::compileEntity() принимает описание блока, его идентификатор или имя. Метод проверяет описание, создает ORM-карту из системного поля ID и пользовательских полей, затем возвращает объект Bitrix\Main\ORM\Entity.

Класс данных наследует Bitrix\Highloadblock\DataManager. Его имя формируется по шаблону \<NAME>Table в глобальном пространстве имен, а метод getTableName() возвращает значение TABLE_NAME из описания блока.

Пример. Получите описание существующего Highload-блока и его класс данных. Перед запуском передайте идентификатор блока в переменной $highloadBlockId.

use Bitrix\Highloadblock\HighloadBlockTable;
use Bitrix\Main\Loader;

if (!Loader::includeModule('highloadblock'))
{
    throw new \RuntimeException('Не удалось подключить модуль highloadblock');
}

$highloadBlock = HighloadBlockTable::getById($highloadBlockId)->fetch();

if (!$highloadBlock)
{
    throw new \RuntimeException('Highload-блок не найден');
}

$entity = HighloadBlockTable::compileEntity($highloadBlock);
$dataClass = $entity->getDataClass();

Переменная $entity содержит ORM-описание, а $dataClass — полное имя класса для запросов и изменений записей. Для запросов, изменения записей и обработки ошибок используйте примеры из статьи Работа с записями.

Обновить ORM-объект после изменения структуры

При первом вызове compileEntity() в текущем запросе модуль создает PHP-класс и ORM-карту. Повторный вызов возвращает созданный объект. Второй аргумент true уничтожает прежнее ORM-описание и строит карту заново, но не переопределяет уже загруженный PHP-класс.

Выбирайте действие по типу изменения:

Изменение

Как продолжить работу

Структура не менялась

Используйте уже полученный класс данных. Повторная компиляция не нужна

Поле добавлено, изменено или удалено через CUserTypeEntity

Продолжите работу с записями в новом запросе. Если сценарий должен завершиться в текущем запросе, получите описание блока заново, вызовите compileEntity($highloadBlock, true) и проверьте наличие ожидаемого поля через hasField()

Изменено поле NAME

Продолжите работу в новом запросе, чтобы код использовал новое имя PHP-класса

Изменено только поле TABLE_NAME

Продолжите работу в новом запросе. Аргумент true не меняет имя таблицы внутри уже загруженного PHP-класса

Методы Add(), Update() и Delete() класса CUserTypeEntity очищают кеш менеджера пользовательских полей. Принудительная компиляция пересобирает ORM-карту по обновленному реестру, но не заменяет новый запрос для изменений имени класса или таблицы.

Изменение структуры

Методы управления структурой изменяют метаданные и хранилище поэтапно. При ошибке уже выполненные шаги могут сохраниться. Не запускайте изменение одного блока параллельно в нескольких процессах.

Перед удалением или переименованием подготовьте резервную копию. После каждой операции проверяйте объект результата и прекращайте зависимые шаги после ошибки. Порядок создания, переименования, удаления и повторяемой миграции приведен в статье Создание, настройка и перенос Highload-блоков.

Имена объектов

Поле NAME определяет имя динамического PHP-класса, а TABLE_NAME — имя хранилища записей. Код пользовательского поля имеет вид UF_*. Окончание _REF зарезервировано для ORM-ссылок, поэтому модуль отклоняет такое имя поля.

Точные ограничения длины, допустимых символов и уникальности собраны в разделе Подготовить имена и подключить модуль.

Связанные материалы

Класс HighloadBlockTable управляет описанием и схемой блока. Динамический класс на базе Bitrix\Highloadblock\DataManager работает с записями. Подробные сценарии сгруппированы по задачам:

Highload-блок связывает настраиваемую схему пользовательских полей с отдельным хранилищем записей и динамической ORM-картой. Сохраняйте эту связь через API модуля: прямое изменение одного слоя не обновляет остальные автоматически.