Каждый PHP-разработчик, работающий с экосистемой Bitrix Framework, должен глубоко понимать работу её ключевых компонентов. В этой статье мы проведем подробный аудит темы «Работа с элементами: Подробное руководство», проанализируем лучшие практики и покажем, как правильно использовать работа элементами в реальных задачах.
Работа с элементами
Взаимодействие с элементами смарт-процессов осуществляется через фабрики (Bitrix\Crm\Service\Factory), получать которые необходимо из контейнера \Bitrix\Crm\Service\Container. Это означает что перед выполнением любой операции необходимо сначала получить контейнер, затем получить необходимую фабрику и уже после выполнить действие.
>Несмотря на то что в некоторых случаях можно обойтись без контейнеров, использование их строго рекомендовано, чтобы обеспечивать возможность наследования и переопределения действий.
[TOC]
Здесь и ниже, мы будем предполагать что работаем с существующим смарт-процессом, который имеет ENTITY_TYPE_ID равный 184.
Перед дальнейшей работой необходимо получить фабрику элементов смарт-процессов.
use \Bitrix\Crm\Service;
/**
* @var Service\Container
*/
$container = Service\Container::getInstance();
/**
* @var Service\Factory\Dynamic
*/
$factory = $container->getFactory( 184 );Получение списка полей
Для получения списка полей смарт-процесса используется метод getFieldsCollection, он возвращает экземпляр Bitrix\Crm\Field\Collection с описанием всех полей элемента смарт-процесса
// ...$factory
$fieldsCollection = $factory->getFieldsCollection();
foreach ($fieldsCollection as $field)
{
/**
* @var $field \Bitrix\Crm\Field
*
* $field->getTitle()
* $field->getName()
*/
}Поиск элементов
Для поиска элементов в каждой фабрике существуют методы getItems и getItemsFilteredByPermissions, которые отождествляют собой прямой доступ к элементам и доступ с учетом прав пользователя.
Прямой поиск
Метод getItems, по параметрам аналогичен ORM методу getList, однако вместо массива массивов, возвращает массив объектов (Bitrix\Crm\Item\Dynamic).
Например: найдем все элементы исходного смарт-процесса, которые содержат букву «a»
$elementsWithA = $factory->getItems([
'filter' => [
'%TITLE' => 'a'
]
]);
foreach ($elementsWithA as $element)
{
echo $element->getTitle();
}С учетом прав
Для поиска элементов смарт-процесса с учетом прав необходимо использовать метод getItemsFilteredByPermissions, который принимает следующие параметры:
$parameters— массив, аналогичный getList$userId— идентификатор текущего пользователя (если не передан — будет учитываться текущий)$operation— уровень прав, который проверяется (по-умолчанию чтение)
Например: найдем все элементы исходного смарт-процесса, которые содержат букву «B» доступных пользователю ID:123
$elementsWithA = $factory->getItemsFilteredByPermissions(
[
'filter' => [
'%TITLE' => 'B'
]
],
123
);
foreach ($elementsWithA as $element)
{
echo $element->getTitle();
}Операции
В этом разделе изложена справочная информация по низкоуровневым возможностям системы.
Если вам необходимо выполнить создание/обновление (сохранение), удаление или конвертацию элемента воспользуйтесь операциями.
Некоторый код расположенный ниже не удовлетворяет критериям:
- Прозрачности (вы не сможете отследить все места и доп.действия с элементом)
- Расширяемости (вы не сможете быстро переопределить или дополнить доп.действиями)
- Консистентности (код ниже не гарантирует корректную работу системы в некоторых частях (поиск, права, таймлайн и т.п.))
Сохранение
Прочитайте примечание к разделу ‘Операция’ прежде чем продолжить чтение.
Оба совершаемых действия (созданию и обновлению) над элементом в объектном подходе обеспечивается методом save, который вызывается на объекте-наследнике Bitrix\Crm\Item, отсюда следует что каждое действие можно провести как минимум 2 путями помимо указанных выше операций.
Вариант с низкоуровневым созданием элемента смарт-процесса:
$item = $factory->getItemByEntityObject(
$factory->getDataClass()::createObject()
);
$item->setTitle('My first element');
// Setup other fields with $item->set* methods
$saveResult = $item->save();
if ( $saveResult->isSuccess() )
{
/**
* Success result
* $item->getId();
*/
}
else
{
/**
* Some errors
* Get error with:
* $saveResult->getErrors();
*
* Get error messages:
* $saveResult->getErrorMessages();
*/
}_Почему данный вариант не подходит для использования разработчиком?_
Это самое низкоуровневое сохранение элемента, в котором не происходит следующих действий:
1. Установка значений по-умолчанию
2. Проверки прав
3. Установки связей
4. Отправки push уведомлений
5. Запуска бизнес-процессов и автоматизаций
6. Перерасчета прав
7. Обновление поискового индекса
8. Учета статистики
9. Формирования timeline
Вариант с более продвинутым созданием объекта:
$initialFields = [
'TITLE' => 'My first element'
];
$item = $factory->createItem($initialFields);
// Setup other fields with $item->set* methods
$saveResult = $item->save();
if ( $saveResult->isSuccess() )
{
/**
* Success result
* $item->getId();
*/
}
else
{
/**
* Some errors
* Get error with:
* $saveResult->getErrors();
*
* Get error messages:
* $saveResult->getErrorMessages();
*/
}_Почему данный вариант не подходит для использования разработчиком?_
Это самое низкоуровневое сохранение элемента, в котором не происходит следующих действий:
1. Установка значений по-умолчанию
2. Проверки прав
3. Установки связей
4. Отправки push уведомлений
5. Запуска бизнес-процессов и автоматизаций
6. Перерасчета прав
7. Обновление поискового индекса
8. Учета статистики
9. Формирования timeline
Рекомендуемый вариант с использованием операций:
$initialFields = [
'TITLE' => 'My first element'
];
$item = $factory->createItem($initialFields);
// Setup other fields with $item->set* methods
$saveOperation = $factory->getAddOperation($item);
$operationResult = $saveOperation->launch();
if ( $operationResult->isSuccess() )
{
/**
* Operation success!
*/
}
else
{
/**
* Some errors
* Get error with:
* $operationResult->getErrors();
*
* Get error messages:
* $operationResult->getErrorMessages();
*/
}Использование операций это рекомендуемый способ по сохранению элемента в полном объеме.
Указанная операция создает элемент, для обновления элемента необходимо получить операцию редактирования (getUpdateOperation).
Удаление
Прочитайте примечание к разделу ‘Операция’ прежде чем продолжить чтение.
Существует несколько способов удаления элемента: низкоуровневый delete и операция по удалению элемента.
Вариант с прямым удалением элемент:
/**
* @item instanceof Bitrix\Crm\Item
*/
$deleteResult = $item->delete();
if ( $deleteResult->isSuccess() )
{
/**
* Item deleted
*/
}
else
{
/**
* Some errors
* Get error with:
* $deleteResult->getErrors();
*
* Get error messages:
* $deleteResult->getErrorMessages();
*/
}_Почему данный вариант не подходит для использования разработчиком?_
Несмотря на то что элемент смарт-процесса фактически удаляется, согласованность данных не обеспечивается, а это значит что не происходит следующих действий:
1. Очистки товарных позиций
2. Очистки записей о правах
3. Очистка связей с событиями
4. Очистки действий
5. Очистки связей с чатами
6. Очистки счетчиков
и т.д.
Рекомендуемый вариант с использованием операций:
/**
* @item instanceof Bitrix\Crm\Item
*/
$deleteOperation = $factory->getDeleteOperation($item);
$operationResult = $deleteOperation->launch();
if ( $operationResult->isSuccess() )
{
/**
* Operation success!
*/
}
else
{
/**
* Some errors
* Get error with:
* $operationResult->getErrors();
*
* Get error messages:
* $operationResult->getErrorMessages();
*/
}Использование операций это рекомендуемый способ по корректному удалению элемента.
💡 Экспертное мнение и рекомендации
Практические рекомендации:
- При написании кастомных компонентов для «Работа с элементами: Подробное руководство» всегда разделяйте бизнес-логику и представление (шаблон).
- Используйте отладку SQL-запросов через конструкцию
$wpdb->last_queryили стандартный трекер Битрикса, чтобы контролировать нагрузку.
Похожая задача в бизнесе?
Помогу автоматизировать процессы и внедрить ИИ
Меня зовут Андрей Горошко. Я Full-stack разработчик и эксперт по 1С-Битрикс. Настраиваю CRM Битрикс24, разрабатываю защищенные API и создаю умных ИИ-агентов для автоматизации рутины.
или на почту: gorandvas@yandex.ru