суббота, 29 сентября 2018 г.

Прерывание работы компонента на классе

При работе с компонентом иногда приходится прерывать работу компонента еще на стадии проверки входных параметров $arParams. Например, если вам требуется ИД инфоблока, а его не указано, то нет смысла заводить всю шарманку с кешированием и прочим, так как получать в общем-то нечего.

В компонентах, построенных на процедурном подходе в файле component.php это решалось приблизительно так:

if (!CModule::IncludeModule('iblock')) {
    ShowError(GetMessage("IBLOCK_MODULE_NOT_INSTALLED"));
    return;
}


В этом случае на странице выводилось красным текстом какое-либо сообщение, и страница продолжала свою работу.
Теперь давайте рассмотрим как реализовать сходное поведение в компоненте на классах (с файлом class.php вместо component.php).

пятница, 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) каким-либо образом исправит положение, но пока что это мечты.

среда, 19 сентября 2018 г.

Методы document.location

Каждый раз когда мне требуется перезагрузить страницу средствами javascript, я пытаюсь вспомнить, что же нужно сделать с объектом document.location. Поэтому сегодня мы быстренько пройдемся по методам данного объекта. Информация взята из MDN, и если вы мне не доверяете, можете обратиться к первоисточнику. Итак, продолжим.