Сентябрь 17, 2018
Теги: Хайлоадблоки, ORM, Хранение данных, События
Использование событий при работе с хайлоадблоками или ORM.
Данные примеры можно использовать при работе как с "чистым" ORM, так и с хайлоадблоками. При использовании для хайлоадблоков, в качестве модуля используется пустая строка - ''.
Подключение обработчика событий для хайлоадблока с прямым указанием сущности "Myentity":
Подключение обработчика события хайлоадблока с получением названия сущности по идентификатору хайлоадблока (12):
namespace Partner\Myentity;
$hlblock = \Bitrix\Highloadblock\HighloadBlockTable::getById(12)->fetch();
$entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock);
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('', $entity->getName().'OnAdd', '\Partner\Myentity\OnAdd');
Подключение обработчика события для сущности ORM "\Grain\Forum\Forum" из модуля "grain.forum":
Получение различных данных из объекта "$event":
$arFields = $event->getParameter("fields"); // получаем список полей
$event->setParameter("fields",$arFields); // обновляем список полей
$entity = $event->getEntity(); // получаем объект сущности
$eventType = $event->getEventType(); // получаем тип события (например, "MyentityOnUpdate")
$moduleId = $event->getModuleId(); // получаем код модуля
Использование событий "OnBeforeAdd", "OnBeforeUpdate":
namespace Partner\Myentity;
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('', 'MyentityOnBeforeUpdate', '\Partner\Myentity\OnBeforeAddUpdate');
$eventManager->addEventHandler('', 'MyentityOnBeforeAdd', '\Partner\Myentity\OnBeforeAddUpdate');
function OnBeforeAddUpdate(\Bitrix\Main\Entity\Event $event)
{
$id = $event->getParameter("id");
if(is_array($id))
$id = $id["ID"];
if(!$id)
return;
$entity = $event->getEntity();
$entityDataClass = $entity->GetDataClass();
$eventType = $event->getEventType();
$arFields = $event->getParameter("fields");
$price = ...
$error = ...
$result = new \Bitrix\Main\Entity\EventResult();
if($error)
{
$arErrors = Array();
$arErrors[] = new \Bitrix\Main\Entity\FieldError($entity->getField("MYFIELD"), "Ошибка в поле MYFIELD");
// или $arErrors[] = new \Bitrix\Main\Entity\EntityError("Общая ошибка");
$result->setErrors($arErrors);
}
else
{
$arFields["UF_AVG_PRICE"] = $price;
$event->setParameter("fields",$arFields);
$changedFields = Array();
$changedFields["UF_AVG_PRICE"] = $price;
$result->modifyFields($changedFields);
//$result->unsetFields($arUnsetFields);
}
return $result;
}
События "OnAdd", "OnUpdate" вызываются после проверки полей на правильность перед добавлением или обновлением элемента:
namespace Partner\Myentity;
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('', 'MyentityOnUpdate', '\Partner\Myentity\OnAddUpdate');
$eventManager->addEventHandler('', 'MyentityOnAdd', '\Partner\Myentity\OnAddUpdate');
function OnAddUpdate(\Bitrix\Main\Entity\Event $event)
{
$id = $event->getParameter("id");
if(is_array($id))
$id = $id["ID"];
$entity = $event->getEntity();
$entityDataClass = $entity->GetDataClass();
$eventType = $event->getEventType();
$arParameters = $event->getParameters();
//$event->setParameters($arParameters);
//$arFields = $event->getParameter("fields");
//$event->setParameter("fields",$arFields);
}
События "OnAfterAdd", "OnAfterUpdate" вызываются после добавления/изменения записи (статическая переменная $bHandlerStop используется для предотвращения рекурсии при вызове Update внутри обработчика, т.к. событие при этом также будет вызываться):
namespace Partner\Myentity;
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('', 'MyentityOnAfterUpdate', '\Partner\Myentity\OnAfterAddUpdate');
$eventManager->addEventHandler('', 'MyentityOnAfterAdd', '\Partner\Myentity\OnAfterAddUpdate');
function OnAfterAddUpdate(\Bitrix\Main\Entity\Event $event)
{
static $bHandlerStop;
if($bHandlerStop===true)
return;
$id = $event->getParameter("id");
if(is_array($id))
$id = $id["ID"];
if(!$id)
return;
$entity = $event->getEntity();
$entityDataClass = $entity->GetDataClass();
$eventType = $event->getEventType();
$arParameters = $event->getParameters();
//$event->setParameters($arParameters);
//$arFields = $event->getParameter("fields");
//$event->setParameter("fields",$arFields);
$bHandlerStop = true;
$result = $entityDataClass::update($id, Array("UF_AVG_PRICE"=>2.0));
$bHandlerStop = false;
}
Пример передачи данных между обработчиками "OnBeforeUpdate" и "OnAfterUpdate" через статическую переменную класса:
namespace Partner;
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('', 'MyentityOnBeforeUpdate', '\Partner\MyClass::onBeforeUpdate');
$eventManager->addEventHandler('', 'MyentityOnAfterUpdate', '\Partner\MyClass::onAfterUpdate');
class MyClass
{
const props = array(
'UF_KINDS_OF_WORK',
'UF_CONSTRUCTION_TYPE',
'UF_REGIONS',
);
private static $temp = null;
function onBeforeUpdate(\Bitrix\Main\Entity\Event $event)
{
$id = $event->getParameter("id");
if(is_array($id))
$id = $id["ID"];
$entity = $event->getEntity();
self::$temp = array(
'id' => $id,
'enumId' => self::getAllEnumId($entity,$id),
);
}
function onAfterUpdate(\Bitrix\Main\Entity\Event $event)
{
$id = $event->getParameter("id");
if(is_array($id))
$id = $id["ID"];
$entity = $event->getEntity();
if(!is_array(self::$temp) || self::$temp['id']!=$id)
return;
$oldEnumId = self::$temp['enumId'];
$newEnumId = self::getAllEnumId($entity,$id);
// ... делаем что-то имея данные, которые были до, и стали после
}
function getAllEnumId($entity,$id)
{
$entityDataClass = $entity->GetDataClass();
$result = $entityDataClass::getList(array(
"select" => self::props,
"filter" => Array("=ID"=>intval($id)),
"limit" => 1,
));
$allEnumId = array();
if($arRow = $result->Fetch())
{
foreach(self::props as $propCode)
if(is_array($arRow[$propCode]))
foreach($arRow[$propCode] as $enumId)
$allEnumId[] = $enumId;
}
return $allEnumId;
}
}
Событие "OnBeforeDelete", возникающее перед удалением элемента (может быть использовано для отмены удаления):
namespace Partner\Myentity;
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('', 'MyentityOnBeforeDelete', '\Partner\Myentity\OnBeforeDelete');
function OnBeforeDelete(\Bitrix\Main\Entity\Event $event)
{
// All $event functions /bitrix/modules/main/lib/event.php
$id = $event->getParameter("id");
if(is_array($id))
$id = $id["ID"];
$entity = $event->getEntity();
$entityDataClass = $entity->GetDataClass();
$result = new \Bitrix\Main\Entity\EventResult();
if($ID==15) {
$arErrors = Array();
$arErrors[] = new \Bitrix\Main\Entity\EntityError("Нельзя удалить запись с ID=".$id);
$result->setErrors($arErrors);
}
return $result;
}
Событие "OnDelete", возникающее перед удалением элемента (уже не может быть использовано для отмены удаления):
namespace Partner\Myentity;
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('', 'MyentityOnDelete', '\Partner\Myentity\OnDelete');
function OnDelete(\Bitrix\Main\Entity\Event $event)
{
// All $event functions /bitrix/modules/main/lib/event.php
$id = $event->getParameter("id");
if(is_array($id))
$id = $id["ID"];
$entity = $event->getEntity();
$entityDataClass = $entity->GetDataClass();
define("ERROR_EMAIL", "my@email.ru");
\SendError("Запись с ID=$id будет удалена\n\n");
}
Событие "OnAfterDelete", возникающее после удаления элемента:
namespace Partner\Myentity;
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('', 'MyentityOnAfterDelete', '\Partner\Myentity\OnAfterDelete');
function OnAfterDelete(\Bitrix\Main\Entity\Event $event)
{
// All $event functions /bitrix/modules/main/lib/event.php
$id = $event->getParameter("id");
if(is_array($id))
$id = $id["ID"];
$entity = $event->getEntity();
$entityDataClass = $entity->GetDataClass();
define("ERROR_EMAIL", "my@email.ru");
\SendError("Запись с ID=$id была удалена\n\n");
}