Работа с окружением
Table of Contents
Любые действия бизнес-процесса для выполнения своих функций должны работать со своим окружением - иметь доступ к чтению параметров, чтению/записи переменных, уметь работать с константами и глобальными значениями. Задача этой главы показать как взаимодействовать с ними. В главе PHP код мы обсуждали, что использование механизма автоподстановки значений с точки зрения кода является очень плохим, хоть и работающим подходом и чем можно его заменить.
Универсальные методы
Парсер
Самый простой способ взаимодействия на чтение с выражением является использование механизма парсинга. Суть данного способа заключается в том, что разбить техническое выражение на части, а затем конкатенировать его при передаче в парсер. Звучит достаточно сложно, но на деле все просто. Представьте себе что у нас есть БП на сущности компания и нам нужно получить его значение, а значит нам достаточно использовать выражение:
$companyTitle = $this->ParseValue('{'.'=Document:TITLE}');
Для получения названия компании. То же самое можно проделать и с любыми другими выражениями, которые вы можете подставить через редактор бизнес процесса.
Метод является нестатическим (т.е. он вызывается только в контексте действия бизнес процесса) и имеет следующую сигнатуру:
\CBPActivity::parseValue($value, $convertToType = null): mixed
Параметры метода:
-
$value
(string) - выражение для парсинга -
$convertToType
(null|string) - код типа, в случае если необходима конвертация.
Очень важно чтобы при использовании указанного кода вы не использовали значения, которые могут попать под автозамену, а это значит что код ниже является ошибочным:
$companyTitle = $this->ParseValue('{=Document:TITLE}');
Дополнительные возможности парсера:
- В нем используется механизм вычисления, а значит вы можете использовать функции бизнес процессов, калькулятор выражений и приведение типов
- В одном парсере можно использовать несколько выражений
Геттер
Помимо парсера в CBPActivity
существует так же универсальный геттер который помогает извлекать значение и мета-информацию по определенному полю.
Сигнатура метода:
\CBPActivity::getRuntimeProperty($object, $field, CBPActivity $ownerActivity): array
Параметры:
-
$object
(string
) - код объекта. Например:Template
,Document
,Variable
и т.п. В качестве значения можно так же использовать константы класса из\Bitrix\Bizproc\Workflow\Template\SourceType
-
$field
(string
) - название поля -
$ownerActivity
(CBPActivity
) - исходное действие.
Метод возвращает неименованый массив из двух элементов: Описания свойства (array
) и Реального значения (mixed
)
Рассмотрим выполнение этого метода как для примера из парсера: мы будем запускать бизнес процесс на сущности компания.
use \Bitrix\Bizproc\Workflow\Template\SourceType;
list($property, $companyTitle) = $this->getRuntimeProperty(
SourceType::DocumentField,
'TITLE',
$this
);
Если вы залоггируем изменения то в наших переменных будут:
$property = [
"Name" => "Название компании",
"Type" => "string",
"Filterable" => true,
"Editable" => true,
"Required" => true,
"BaseType" => "string",
];
$companyTitle = "Веб-сервис";
В классе SourceType
помимо указанного DocumentField
так же доступны:
-
SourceType::DocumentField
-
SourceType::Parameter
-
SourceType::Variable
-
SourceType::Constant
-
SourceType::GlobalConstant
-
SourceType::GlobalVariable
-
SourceType::System
-
SourceType::Activity
-
SourceType::CalcFunction
Параметры
Параметры бизнес-процесса, это значения которые указываются при запуске, таким образом они остаются постоянными в ходе работы с бизнес процессом. Для того чтобы обратиться к параметру необходимо явно знать его код.
Например, мы создали в бизнес-процессе параметр с кодом Parameter1
(значением кода по-умолчанию для первого создаваемого параметра), то для того чтобы получить его на чтение необходимо:
- Получить объект корневого действия (т.е. действия являющегося верхнеуровневым для бизнес-процесса)
- Обратиться к его свойству с названием параметра
Таким образом код будет выглядеть следующимим образом:
$rootActivity = $this->getRootActivity();
$ourValue = $rootActivity->Parameter1;
Переменные
В отличии от параметров переменные могут изменяться в ходе всего бизнес-процесса, поэтому у действия (CBPActivity
) есть методы как на чтение getVariable
, так и на запись setVariable
.
Сигнатуры нестатических методов:
/**
* @param string $name - Variable name
* @return mixed|null If value not exist - null. If multiple values - array
*/
\CBPActivity::getVariable($name): mixed|null
/**
* @param string $name - Variable name
* @param mixed $value - Variable value
* @return void
*/
\CBPActivity::setVariable($name, $value): void
Например, мы хотим записать переменную ApprovedByUsers
с типом “Привязка к сотрудникам” (множественная) и сразу же ее прочитать:
$this->setVariable(
'ApprovedByUsers',
[
'user_1',
'user_2',
]
);
$users = $this->getVariable('ApprovedByUsers');
Константы
Константы это неизменяемые значения для запущенного шаблона бизнес-процесса. Их поведение похоже на параметры, однако задать их можно только в дизайнере бизнес процесса при редактировании шаблона. Метода на изменение констант не существует.
Для получения константы существует нестатический метод:
/**
* @param string $name - Contant name
* @return mixed|null If value not exist - null. If multiple values - array
*/
\CBPActivity::getConstant($name): mixed|null
Предположим, что у нас есть константа hr_user
, которую мы задали в шаблоне бизнес процесса. Тогда ее получение будет выглядеть следующим образом:
$ourHrUser = $this->getConstant('hr_user');
Сущность
Очень часто для получения сущности используются один из двух способов: либо прямое получение данных (посдтановка, парсинг, геттер), либо получение ID текущей сущности и дополнительные запросы в базу данных. В случае с парсингом и геттером это является допустимым, однако в остальных случаях это не самый эффективный способ. Мы уже знаем что бизнес процесс запускается по шаблону на определенной сущности, а значит к полям этой сущности у нас есть довольно простой доступ - работа через сервис документов.
Пример работы:
$documentId = $this->getDocumentId();
/**
* @var CBPDocumentService
*/
$documentService = $this->workflow->getService('DocumentService');
/**
* @var Bitrix\Bizproc\Document\ValueCollection
*/
$document = $documentService->getDocument($documentId);
echo $document['TITLE'];
Преимущество работы с использованием данного способа:
-
DocumentService
имеет локальное кеширование. Повторный вызов метода не вызовет запрос на получение данных, а значит все активити которые будут работать с данным сервисом не будут иметь накладных расходов в виде запросов в базу данных. Он так же является Lazy-load, а значит простой вызов кода не сделает запросов в базу даннхы. - Универсален. Не важно с какой сущностью вы работаете - сервис получит необходимые данные, а удобство работы с ArrayAccess позволит быстро к нему обратиться
- Выполняется без проверки прав. Вы всегда получите сущность и ее поля даже если забудете дописать
CHECK_PERMISSION => N
.
Глобальные хранилища
Глобальные переменные и глобальные константы имеют одинаковое поведение поскольку являются реализацией одного абстрактного механизма - глобального менеджера. Важно заметить, что поведение глобальных констант отличается от констант в шаблоне бизнес процесса - они могут изменяться. То есть поведение глобальных констант и глобальных переменных с точки зрения кода - одинаковое.
Абстрактно это можно представить следующим образом:
use \Bitrix\Bizproc\Workflow\Type\GlobalsManager;
use \Bitrix\Bizproc\Workflow\Type\GlobalVar;
use \Bitrix\Bizproc\Workflow\Type\GlobalConst;
class GlobalVar extends GlobalsManager {}
class GlobalConst extends GlobalsManager {}
Поскольку все методы находятся в родительском классе GlobalsManager
, то мы будем рассматривать именного его работу, а не конкретную реализацию.
Поскольку глобальное хранилище зависимо от сущности (в crm свои глобальные константы, а в rpa другие) для работы с ними необходимо использовать массив описания типа документа ($documentType
)
Пример типа документа для CRM сущности Компания:
['crm', 'CCrmDocumentCompany', 'COMPANY']
Пример получения списка глобальных переменных:
use \Bitrix\Bizproc\Workflow\Type\GlobalVar;
$documentType = ['crm', 'CCrmDocumentCompany', 'COMPANY'];
$allEntities = GlobalVar::getAll($documentType);
// Пример содержимого
$allEntities = [
"Variable1684762282405" => [
"Name" => "Test",
"Description" => "",
"Type" => "string",
"Required" => false,
"Multiple" => false,
"Options" => "",
"Default" => "",
"CreatedBy" => 1,
"CreatedDate" => new Bitrix\Main\Type\DateTime(),
"Visibility" => "GLOBAL",
"ModifiedBy" => 1,
"ModifiedDate" => new Bitrix\Main\Type\DateTime(),
]
];
Примечание:
Visibility
может принимать значения:GLOBAL
,<module>
,<module>_<entity>
. Переменные отображаемые только в CRM компаниях могут иметь значенияGLOBAL
,CRM
иCRM_COMPANY
.
С обновлением значения свойства намного сложнее - для того чтобы обновить значение, необходимо обновлять описание всего свойства. Поэтому изменение будет выглядеть как набор команд: получение описания, изменение описания и сохранение значения.
Для сохранения используется команда:
use \Bitrix\Bizproc\Workflow\Type\GlobalsManager;
public static function upsert($id, $property, int $userId = null): bool
Параметры:
-
$id
(string) - код свойства -
$property
(array) - ассоциативный массив описывающий свойство -
$userId
(null|int) - идентификатор пользователя создающего/изменяющего свойство
Пример изменения глобальной переменной:
use \Bitrix\Bizproc\Workflow\Type\GlobalVar;
$variableId = 'Variable1684762282405';
$property = GlobalVar::getById($variableId);
if ( is_null($property) )
{
throw new \Exception("Property not exist: ".$variableId);
}
$property['Default'] = "new value";
GlobalVar::upsert($variableId, $property);
Для удаления глобальной переменной используется статический метод delete
:
use \Bitrix\Bizproc\Workflow\Type\GlobalVar;
$variableId = 'Variable1684762282405';
GlobalVar::delete($variableId); //return true if success or false otherwise
Дополнительные значения
В рамках действия (CBPActivity
) существует так же набор методов для получения полезной информации:
/**
* Return document identifier
* e.g. ['crm', 'CCrmDocumentCompany', 'COMPANY_123']
* @var array
*/
$documentId = $this->getDocumentId();
/**
* Return document type identifier
* e.g. ['crm', 'CCrmDocumentCompany', 'COMPANY']
* @var array
*/
$documentType = $this->getDocumentType();
/**
* Return workflow template identifier
* @var string
*/
$wfTemplateId = $this->getWorkflowTemplateId();
/**
* Template user id (who start process)
* @var int
*/
$templateUserId = $this->getTemplateUserId();
/**
* Return root bizproc activity
* @var \CBPActivity
*/
$rootActivity = $this->getRootActivity();