Безопасное обновление заказа без рекурсии событий
Защита от бесконечной рекурсии при обновлении заказа через флаг контекста и логирование изменений.
Как использовать
- Скопируйте нужный фрагмент кода.
- Вставьте в свой проект и при необходимости измените под задачу.
- Проверьте зависимости и окружение (версии, переменные).
Предотвращает бесконечную рекурсию при обновлении заказа в обработчике события OnSaleOrderSaved. Используйте флаг контекста и логирование для отладки.
use Bitrix\Main\Event;
use Bitrix\Sale\Order;
// Статический флаг для предотвращения рекурсии
static $updateInProgress = false;
AddEventHandler('sale', 'OnSaleOrderSaved', function(Event $event) {
$order = $event->getParameter('ENTITY');
if (!($order instanceof Order)) {
return;
}
global $updateInProgress;
// Проверяем флаг, чтобы избежать рекурсии
if ($updateInProgress) {
return; // Уже обновляем, выходим
}
// Устанавливаем флаг
$updateInProgress = true;
try {
// Логируем изменение (если логгер настроен в .settings.php)
if (class_exists('\Bitrix\Main\Diag\Logger')) {
$logger = \Bitrix\Main\Diag\Logger::create('order_update');
if ($logger) {
$logger->info('Order update started', [
'order_id' => $order->getId(),
'status' => $order->getField('STATUS_ID')
]);
}
}
// Ваша логика обновления
if ($order->getField('STATUS_ID') === 'N') {
// Обновляем без триггера события (параметр false отключает события)
$order->setField('COMMENTS', 'Updated by handler');
$order->save(false);
}
if (isset($logger) && $logger) {
$logger->info('Order update completed', ['order_id' => $order->getId()]);
}
} finally {
// Снимаем флаг
$updateInProgress = false;
}
});
Usage:
Добавьте в /local/php_interface/init.php или в модуле. Флаг предотвратит повторный вызов обработчика при сохранении.
Notes:
⚠️ Используется статический флаг $updateInProgress для предотвращения рекурсии. Метод $order->save(false) с параметром false отключает события при сохранении. Logger требует настройки в .settings.php (см. документацию Bitrix). Альтернатива без логгера — просто убрать блок с Logger::create().