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

PHP-код в бизнес-процессе - переменные, типы, отладка

Пишем код внутри бизнес-процесса: читаем переменные, записываем результат и отлаживаем то, что нигде на экран не выводится.

Решение

Читаем поля документа и переменные процесса:

// внутри действия «PHP-код»: $this - экземпляр процесса
$rootActivity = $this->GetRootActivity();
$documentId = $rootActivity->GetDocumentId();
$responsible = $rootActivity->GetVariable('Responsible');
$state = $rootActivity->GetStateTitle(); // текущее состояние процесса
// имена переменных задаются в дизайнере и чувствительны к регистру
// поля документа приходят подстановками из дизайнера, а не читаются напрямую

Действие с кодом выполняется внутри процесса, а не в контексте страницы. Данных запроса здесь нет вовсе, а всё нужное берётся из переменных процесса и полей документа.

Записываем значение в переменную процесса:

$rootActivity = $this->GetRootActivity();
$rootActivity->SetVariable('Result', 'обработано');
// переменная доступна всем следующим действиям процесса
$rootActivity->SetVariable('ProcessedAt', date('d.m.Y H:i:s'));

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

Разбираемся с полями типа «список»:

// в переменной лежит код значения, а не его текст
$status = $rootActivity->GetVariable('Status'); // например, APPROVED
if ($status === 'APPROVED') { // сравниваем с кодом, не с текстом
$rootActivity->SetVariable('Result', 'согласовано');
}

Поля-списки хранят внутри себя коды значений. Сравнение с текстом значения в условии не сработает никогда, и это самая частая причина жалобы «условие не выполняется, хотя значение то самое».

Отлаживаем код процесса:

file_put_contents('/home/bitrix/www/upload/bp.log',
date('c') . ' ' . print_r($rootActivity->GetVariable('Result'), true) . "\n",
FILE_APPEND);
// вывод на экран из процесса не виден: он выполняется вне страницы

Печать на экран в процессе бесполезна: он выполняется в фоне или в обработчике сохранения документа. Запись в файл остаётся единственным способом увидеть, что там на самом деле происходит.

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

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

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

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

Значение не доходит до следующего действия.

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

Условие по полю-списку не срабатывает.

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

Код ничего не выводит.

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

Процесс остановился без сообщения.

В коде действия произошла ошибка выполнения. Экземпляр процесса прекращает работу в этой точке и остаётся в ней навсегда.

Сохранение документа стало медленным.

Тяжёлый код внутри процесса выполняется прямо в момент сохранения документа. Долгие операции из процесса выносят в отдельный агент.

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

Можно ли обойтись без кода в процессе?

Штатных действий хватает для условий, задач и уведомлений. Код нужен там, где требуется обращение к своим данным или к внешней системе.

Как получить элемент списка, зная только его название?

Выборкой по инфоблоку списка внутри кода. Название не уникально, поэтому в условиях полагаются на код или идентификатор.

Почему код не видит подключённых модулей?

Модули подключают явно, как в любом своём коде. Процесс не поднимает ничего сверх ядра платформы.

Как проверить код, не запуская процесс целиком?

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

Смежное

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