Перейти к содержимому

Своя логика при обмене - обработчики, защита правок, журнал

Дорабатываем приезжающие из учётной системы данные: защищаем правки сайта, дописываем свои значения и не превращаем сеанс обмена в многочасовой.

Решение

Ловим событие сохранения элемента:

use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler('iblock', 'OnBeforeIBlockElementUpdate',
['\\Vendor\\Exchange', 'beforeUpdate']);
// приезжающие из обмена товары проходят те же события, что и ручная правка

Данные обмена проходят обычные события сохранения элемента. Отсюда возможность вмешаться, и отсюда же главная опасность: обработчик выполнится столько раз, сколько позиций в файле обмена.

Отличаем обмен от ручной правки:

public static function beforeUpdate(&$fields): void
{
$isImport = isset($_REQUEST['mode']) && $_REQUEST['mode'] === 'import';
if (!$isImport) { return; } // ручную правку не трогаем
// дальше правим только то, что действительно приехало из обмена
}

Признак режима отделяет сеанс обмена от работы контент-менеджера. Без этой проверки защита полей начинает мешать редактированию товара руками, и жалобы приходят уже от своей же команды.

Защищаем поля, которые ведёт сайт:

unset($fields['PREVIEW_TEXT'], $fields['DETAIL_TEXT']); // тексты правит сайт
unset($fields['IBLOCK_SECTION']); // и привязки к разделам
// снятое из набора поле остаётся в базе прежним

Снятое из набора поле обмен не переписывает. Это и есть защита правок: учётная система остаётся хозяином цен и остатков, а описания и подборки живут на сайте и переживают ночной сеанс.

Дописываем свои значения и пишем журнал:

$fields['PROPERTY_VALUES']['IMPORTED_AT'] = date('d.m.Y H:i:s');
\Bitrix\Main\Diag\Debug::writeToFile(
['id' => $fields['ID'], 'name' => $fields['NAME']], date('H:i'), 'exchange.log');
// запись в журнал на каждую позицию заметно замедляет большой сеанс

Журнал на каждую позицию замедляет обмен на большом каталоге. Записывают либо только необычные случаи, либо итог сеанса, а не каждое сохранение подряд.

Ошибка в обработчике роняет весь сеанс обмена. Код здесь пишут защищённым: непойманное исключение обрывает загрузку на середине, и каталог остаётся наполовину обновлённым.

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

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

Типичные проблемы

Контент-менеджер не может сохранить товар.

Обработчик снимает поля и при ручной правке тоже. Режим обмена отличают по признаку запроса.

Обмен стал длиться часами.

В обработчике идут запросы к базе или запись в журнал. Он выполняется на каждой позиции файла обмена.

Сеанс обрывается на середине.

Обработчик бросает исключение на одной из позиций. Непойманная ошибка прекращает всю загрузку.

Тексты всё равно перезаписываются.

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

Свои значения не сохранились.

Свойства записаны не в тот ключ набора полей. Значения свойств лежат в отдельном ключе, а не рядом с полями элемента.

Частые вопросы

Где регистрировать обработчик обмена?

В файле обработчиков своего решения или модуля. Регистрация в шаблоне страницы на сеанс обмена не действует.

Можно ли отменить сохранение позиции?

Да, вернув признак отмены, но осторожно: учётная система об этом не узнает и будет считать позицию выгруженной.

Как понять, сколько времени съедает обработчик?

Замерить время сеанса с ним и без него на одинаковом файле. Разница и есть его цена.

Что лучше: обработчик или правка после обмена?

Обработчик точнее, отдельный проход после обмена безопаснее. На больших каталогах чаще выбирают второе.

Смежное

Первоисточник