пятница, 21 сентября 2018 г.

Кеширование пропертей инфоблока

Сегодня столкнулся со следующей проблемой: в скрипте импорта выполняются два абсолютно одинаковых CIBlockElement::GetList. Между ними происходит одно важное действие - пересоздание свойства инфоблока (удаление и создание заново с таким же кодом). Казалось бы, может ли что-то пойти не так? Как оказалось - может.

Суть в том, что когда вы в GetList пытаетесь отфильтровать записи по фильтру типа:
[
    'IBLOCK_ID' => $this->arParams['IBLOCK_ID'],
    'ACTIVE' => 'Y',
    'ACTIVE_DATE' => 'Y',
    'PROPERTY_FOO' => 'BAR',
],

то происходит следующее:
  • битрикс по коду FOO свойства находит о нем информацию в таблице b_iblock_property
  • из этой информации извлекается ИД свойства и подставляется в запрос, получается условие вида WHERE tablename.PROPERTY_42 = 'BAR', где 42 - это ИД свойства с кодом FOO
  • битрикс кеширует эту информацию в простом массиве с ключом определенного формата
  • последующие GetList с использованием свойства с данным кодом и для данного инфоблока обращаются к этому кешу и вытягивают из него ИД свойства.

В моем случае свойство удалялось из таблицы, но не удалялось из этого кеша. Таким образом, условие WHERE tablename.PROPERTY_42 = 'BAR' хранило код старого, уже удаленного свойства с кодом FOO, а про новое не знало.
Какое решение? Правильно, очистить кеш. Так как кеш - это простой массив, хранящийся как глобальная переменная (это же ведь битрикс), то достаточно сделать нечто такое:

$GLOBALS['IBLOCK_CACHE_PROPERTY'] = [];

Естественно, при этом затирается информация о всех пропертях, поэтому поосторожнее с таким подходом. Но в моем варианте, при работе с одним инфоблоком, данный костыль очень выручил. Кстати, работа с данным массивом происходит в методе CAllIBlockProperty::GetPropertyArray.

А вот зачем мне понадобилось пересоздавать свойство - это уже совсем другая история.

P.S. Возможно, переход на D7 (когда в D7 появится возможность тянуть проперти через ORM) каким-либо образом исправит положение, но пока что это мечты.

Комментариев нет:

Отправить комментарий