События ORM/хайлоадблоков

Сентябрь 17, 2018

Теги: Хранение данных, События, Хайлоадблоки

Использование событий при работе с хайлоадблоками или ORM.

Данные примеры можно использовать при работе как с "чистым" ORM, так и с хайлоадблоками. При использовании для хайлоадблоков, в качестве модуля используется пустая строка - ''.

Подключение обработчика событий для хайлоадблока с прямым указанием сущности "Myentity":


namespace Partner\Myentity;


$eventManager = \Bitrix\Main\EventManager::getInstance();

$eventManager->addEventHandler('''MyentityOnAdd''\Partner\Myentity\OnAdd');

Подключение обработчика события хайлоадблока с получением названия сущности по идентификатору хайлоадблока (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":


namespace Partner\Myentity;


$eventManager = \Bitrix\Main\EventManager::getInstance();

$eventManager->addEventHandler('grain.forum''\Grain\Forum\Forum::onAfterAdd''\Partner\Myentity\OnAfterAdd');

Получение различных данных из объекта "$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");
}

← Переход к списку