Действие: PHP код
Table of Contents
Иногда возникает необходимость расширить стандартные возможности бизнес-процессов, а для этого в коробке есть большой набор инструментов, одним из которых является действие “PHP код”.
Мы настоятельно не рекомендуем использовать это активити в релизах, поскольку данное действие помимо своих сильных сторон имеет очевидные слабые стороны.
Преимущества:
- Позволяет расширять возможности бизнес-процессов
- Занимают минимальное время на разработку
Недостатки:
- Некорректно описанный код может заблокировать процесс
- При наличии активити в схеме бизнес-процесса, редактировать бизнес-процесс могут только сотрудники с правами на изменение физических файлов портала (административный доступ)
- Большие активити с течением времени сложно поддерживать
Правила
В случае если вы решили писать активити старайтесь следовать правилам:
- Чем меньше кода тем проще его отладить. Старайтесь использовать код который можно отладить и без активити.
- Оборачивайте код в try-catch блок ожидая Throwable. Таким образом вы предотвратите неожиданные и необъяснимые падения.
- Записывайте все что может быть важно. Успешное выполнение, ошибка или неожиданное поведение.
- Не используйте код, который интерпретируется парсером битрикса (например
{ID}
автоматически заменяемый) - Не опирайтесь на глобальные переменные. Код может выполнять как на странице, так и на cron - переменная с текущим пользователем может быть пуста или заполнена не тем сотрудником. Идентификатора сайта может не быть.
Журналирование
Для того чтобы делать записи в журнал бизнес-процесса существует специальный сервис журналирования (TrackingService
) и быстрая log-функция \CBPActivity::WriteToTrackingService
.
Так как любое действие (активити) является наследником этого класса, то обращаться к нему можно через $this
часть.
Сигнатура метода:
/**
* @param string $message Message to log
* @param int $modifiedBy Who modifier
* @param int $trackingType Tracking type
* @type void
*/
\CBPActivity::WriteToTrackingService($message = "", $modifiedBy = 0, $trackingType = -1): void
Параметрами данного метода являются:
-
$message
(string) - Текстовая строка, которая будет записана в журнал бизнес-процесса. -
$modifiedBy
(int) - Идентификатор сотрудника, который будет записан в журнал.0
- соответствует системе. -
$trackingType
(enum) - Тип сообщения (см. Типы сообщений).
Пример записи обычного сообщения в журнал:
$this->WriteToTrackingService(
"Some message!",
0,
\CBPTrackingType::Report
);
Интересная особенность, если использовать запись в журнал, то строка будет обработана так же как и любое значение, т.е. переменные будут заменены согласно калькулятору выражений.
Типы сообщений
Зарегистрированные типы сообщений хранятся константами в классе CBPTrackingType
, однако констант в классе гораздо больше чем отображаемых в журнале сообщений.
Все типы сообщений в журнале отображаются одинаково, однако семантически лучше разделять их для возможного последующего использования в коде
Отображаемые сообщения:
-
\CBPTrackingType::Error
- Ошибки в процессе работы -
\CBPTrackingType::Report
- Примечания в процессе работы -
\CBPTrackingType::Custom
- Сообщения неопределенного типа -
\CBPTrackingType::FaultActivity
- Критическая ошибка при работе действия
Шаблон активити
try
{
// ... code here ...
}
catch( \Throwable $e )
{
$this->WriteToTrackingService(
sprintf("Error %s on line %s in file %s",
$e->getMessage(),
$e->getLine(),
$e->getFile()
),
0,
CBPTrackingType::FaultActivity
);
}
Окружение
В действиях бизнес-процесса часто необходимо взаимодействовать с окружением - переменными процесса, параметрами, константами, глобальными константами и переменными, полями документа. Самое очевидное, что приходит на ум всем - использовать подстановку переменных через стандартный редактор.
Представим самый обычный код:
$testMessage = "Entity id: {{Название компании}}";
$this->WriteToTrackingService($testMessage);
Код выглядит, запуститься и даже будет выдавать результат, однако в данном случае в нем кроется часовая бомба.
В чем проблема? Представим грубо, что любая заменя это просто набор str_replace
, т.е. переменные будут заменены как есть. Что произойдет если в заменяемой фразе будет кавычка?
Например: в названии компании указано значение ООО "Супер сила"
Таким образом код выглядит следующим образом:
$testMessage = "Entity id: ООО "Супер сила"";
$this->WriteToTrackingService($testMessage)
Заметили синтаксическую ошибку? Именно - указанный фрагмент будет вызывать фатальную ошибку. Теперь когда вы поняли почему нельзя работать с автозаменой давайте разберем техники как этого обойти.
Парсинг
Из курса по бизнес-процессам нам известно о существование таких элементов как парсер (выполняет автозамену) и калькулятор выражений (парсит и вычисляет значения).
За парсинг значений отвечает метод \CBPActivity::parseValue($value, $convertToType = null)
, тогда у нас есть возможность использовать ее для своих нужд.
$this->ParseValue('{'.'=Document:TITLE}')
Правда тут есть одна неприятность: необходимо использовать не отображаемое значение, а реальное. Так например
{{ID}}
станет{=Document:ID}
. Тогда{{Название компании}}
станет{=Document:TITLE}
.
Таким образом наш преобразованный код будет выглядеть так:
$testMessage = "Entity id: ".$this->ParseValue('{'.'=Document:TITLE}');
$this->WriteToTrackingService($testMessage);
Почему мы не написали
ParseValue('{=Document:TITLE}')
? Дело в том, что в таком случае сработала бы автозамена и мы получили такую же ошибку, как и ранее, поэтому мы сознательно разделили нашу запись чтобы автозамена значений битрикса не сработала.