Когда хайлоад блок используется чуть менее тривиально, чем простой справочник, появляется необходимость хранить где-то свои методы работы с ним. Самое лучшее место - сам класс HL-блока. Казалось бы - берём базовый класс в соответствии с документацией, наследуем, работаем. Но всё оказывается неможко не так:-)
Следуя документации, пишем код для hl-блока с идентификатором 1 и кодом сущности Test:
namespace nav;
use Bitrix\Highloadblock as HL;
$hlblock = HL\HighloadBlockTable::getById(1)->fetch();
$entity = HL\HighloadBlockTable::compileEntity($hlblock);
$entityClass = $entity->getDataClass();
class TestTable extends \TestTable {
...
}
У сущности Test есть поле PARENT_ID, попробуем выбрать записи с фильтром по нему:
[Bitrix\Main\SystemException] Unknown field definition `PARENT_ID` (PARENT_ID) for Test Entity. (100)
Проверка кода и названия поля ничего не даёт, мало того, та же выборка через $entityClass::getList() успешно отрабатывает.
А теперь немного о том, как работает компиляция сущности в модуле HighloadBlock. Внутри метода объявляется класс с именем ИмяСущностиTable, в котором описывается только одно поле - ID. И тут создаётся объект этого класса, к которому добавляются все поля hl-блока так же, как если бы это было сделано статически в getMap() сущности. Данный экземпляр класса является синглтоном и хранится в датаменеджере ORM по ключу, равному имени класса ("ИмяСущностиTable"). И все будущие обращения к нашей скомпилированной сущности оперируют этим синглтоном.
Таким образом, после вызова HL\HighloadBlockTable::compileEntity() мы имеем:
Базовый класс сущности с только одним полем ID;
Зарегистрированный по имени класса синглтон со всеми полями HL-блока.
Именно по этому всё хорошо работает, пока мы ничего не трогаем.
Теперь взглянем на метод создания/получения синглтона сущности в ORM (\Bitrix\Main\Entity\DataManager):
public static function getEntity()
{
$class = get_called_class();
if (!isset(static::$entity[$class]))
{
static::$entity[$class] = Base::getInstance($class);
}
return static::$entity[$class];
}
В первой же строке видно, как определяется ключ для хранения нашего синглтона - по имени класса, полученного в результате late state binding. Таким образом, становится очевидна причина, по которой выборка в классе-наследнике не знает о пользовательском поле PARENT_ID - порождается новый синглтон без маппинга полей.
Чтобы избежать этой проблемы (либо недомолвки в документации), надо всего лишь в наследуемом классе переопределить getEntity(), чтобы тот возвращал исходный синглтон. Весь код наследования целиком будет выглядеть следующим образом:
namespace nav;
\Bitrix\Main\Loader::includeModule('highloadblock');
use Bitrix\Highloadblock as HL;
\Bitrix\Highloadblock\HighloadBlockTable::compileEntity(array(
'ID' => 1,
'NAME' => 'Test',
'TABLE_NAME' => 'b_custom_test'
));
class TestTable extends \TestTable
{
public static function getEntity()
{
return static::$entity['TestTable'];
}
}
Долганин Антон, да, я их использую именно из-за интерфейса. Ну или когда надо хранить что-то большое и/или часто удаляемое, дабы не увеличивать айдишники элементов инфоблоков. Меня больше всего коробили префиксы UF_, но маленький обработчик позволяет от них избавиться быстро, без последствий и смс, так что теперь я вполне доволен:-)
Долганин Антон написал: а с таблицами работаю на уровне API D7
Так это ж и так орм, только с лишними действиями вначале. Или ты имеешь ввиду sqlhelper + прямые запросы?
Нейман Андрей написал: Меня больше всего коробили префиксы UF_,
Так ОРМ позволяет от них уйти: select = array('BLABLA' => 'UF_BLABLA');
Я имею в виду не прямые запросы, а: 1. берем делаем карту таблицы hl-блока (ведь он таблица прежде всего) 2. пишем какую угодно логику, используя getList/add/update
Вот и спросил - чего я лишаюсь, не юзая родное API hl-блоков
И морально ничего не тревожит, и интерфейсик в админке базовый есть.
Я имею в виду не прямые запросы, а: 1. берем делаем карту таблицы hl-блока (ведь он таблица прежде всего) 2. пишем какую угодно логику, используя getList/add/update
А, понял - всё та же ормка. Я тоже сначала так начинал, пока не было необходимости связываться со множественными свойствами - лениво было описывать подклассы для них, а рерайтить битриксовый код ради NIH тоже не хотелось.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».