При работе с HL-блоками мы постоянно пишем:
$hlblock = HL\HighloadBlockTable::getById($id)->fetch();
$entity = HL\HighloadBlockTable::compileEntity($hlblock); // <-- Здесь происходит магия
$entityClass = $entity->getDataClass();Метод compileEntity «на лету» собирает класс сущности, анализируя пользовательские поля.
Это требует ресурсов. Если вы вызываете этот код в цикле или несколько раз в разных компонентах на одной странице, вы теряете производительность.
Паттерн: Singleton для сущностей
Лучшая практика — создать сервисный класс, который будет хранить скомпилированные классы в статическом свойстве.
namespace My\Project;
use Bitrix\Highloadblock\HighloadBlockTable;
use Bitrix\Main\Loader;
class HLBlockFactory
{
private static $classes = [];
/**
* Возвращает класс сущности HL-блока по его ID или NAME
* @param int|string $identifier ID или Название (TABLE_NAME) HL-блока
* @return string|null Имя класса или null
*/
public static function getClass($identifier)
{
if (isset(self::$classes[$identifier])) {
return self::$classes[$identifier];
}
Loader::includeModule('highloadblock');
// Пытаемся найти HL-блок
// Если передан ID (число)
if (is_numeric($identifier)) {
$hlblock = HighloadBlockTable::getById($identifier)->fetch();
} else {
// Если передано название таблицы
$hlblock = HighloadBlockTable::getList([
'filter' => ['=TABLE_NAME' => $identifier]
])->fetch();
}
if (!$hlblock) {
return null;
}
// Компилируем
$entity = HighloadBlockTable::compileEntity($hlblock);
$dataClass = $entity->getDataClass();
// Кэшируем результат в статику
self::$classes[$identifier] = $dataClass;
// Можно закэшировать и по ID, и по TABLE_NAME, чтобы не искать второй раз
self::$classes[$hlblock['ID']] = $dataClass;
self::$classes[$hlblock['TABLE_NAME']] = $dataClass;
return $dataClass;
}
}Как использовать
use My\Project\HLBlockFactory;
// Первый вызов: будет запрос к БД и компиляция
$brandClass = HLBlockFactory::getClass('b_brands');
$brands = $brandClass::getList([])->fetchAll();
// ... где-то в другом компоненте ...
// Второй вызов: вернется мгновенно из статического массива
$brandClass = HLBlockFactory::getClass('b_brands');Вывод:
Избегайте дублирования вызовов compileEntity в рамках одного хита.
Использование простой фабрики-обертки сделает ваш код чище и быстрее, особенно на страницах с большим количеством компонентов.
compileEntity кэширование, HighloadBlockTable::compileEntity, оптимизация HL-блоков, HLblock производительность, getTable.