Обработчики событий в модулях Битрикс. События в битриксе
Обработчики событий в модулях Битрикс
В Битриксе мощный функционал событий, который позволяет расширять и изменять стандартную логику системы не вмешиваясь в её внутренний код, а следовательно не мешая обновлению ядра. Любой программист на Битриксе хоть раз регистрировал свои обработчики для работы с отправкой писем или добавлением товара в корзину, или оформлением заказа, или для работы с чем-либо ещё. Для этого мы просто пишем код, зачастую в init.php, где регистрируется обработчик и описывается его логика.
Но как вы зарегистрируете обработчик при установке своего модуля? Куда положите код обработчика? Как отвяжете его при удалении модуля?
Некоторые разработчики знают, что есть функции наподобие:
\Bitrix\Main\EventManager::getInstance()->registerEventHandler()и
\Bitrix\Main\EventManager::getInstance()->unRegisterEventHandler()Они позволяют регистрировать обработчик события изнутри модуля. Но вы должны дополнительно позаботиться о вызове этого метода с нужными параметрами и в нужное время. И как-то организовать внутри модуля хранения кода обработчика. Это чисто техническая проблема, а есть ещё и другие.
Ведь как уже упоминалось, система событий Битрикса очень мощная, но это несёт свои определённые трудности. Событий в cms сотни, они вызываются из десятков стандартных модулей и передают разные параметры. Довольно сложно просто узнать про каждое из них, не говоря уже о том, что держать их в памяти.
Но с этими двумя проблемами успешно справляется Конструктор модулей. Чтобы добавить обработчик события в свой модуль, нужно просто заполнить лаконичную форму, где вы укажите модуль, вызывающий событие, и код самого события.
А после этого просто вставить код в специальное окно.
Причём при вводе кода модуля или события вам предлагаются возможные варианты. А после заполнения этих двух полей входные параметры для обработчика подставляются автоматически.
И это всё что нужно! Не нужно думать над реализацией, хранением, установкой и удалением, просто указываете в форме при каком событии, какой код должен выполниться.
Попробуйте воспользоваться этим удобством бесплатно прямо сейчас и добавить обработчик события в свой модуль.
modules-constructor.ru
Bitrix event события init.php — Библиотека кода
<?php
// Add custom field in email send order
AddEventHandler("sale", "OnOrderNewSendEmail", Array("EmailHandler", "SendInvoice"));
// require field and throw
AddEventHandler("main", "OnBeforeUserRegister", Array("UserHandler", "RequireField"));
AddEventHandler("main", "OnBeforeUserUpdate", Array("UserHandler", "RequireField"));
// PersonType If user IsAuthorized
AddEventHandler("sale", "OnSaleComponentOrderOneStepPersonType", Array("UserHandler", "PersonTypeOrderMake"));
// add custom field out $_REQUEST
AddEventHandler("main", "OnBeforeUserRegister", Array("UserHandler", "HandlerAddSecondName"));
// проверка login только латинские символы и цифры
AddEventHandler("main", "OnBeforeUserRegister", Array("UserHandler", "LoginCheck"));
AddEventHandler("main", "OnBeforeUserUpdate", Array("UserHandler", "LoginCheck"));
// Регистрация пользователя через корзину
AddEventHandler("main", "OnBeforeUserAdd", Array("GuestHandler", "RegistrationUser"));
// Восстановление пароля
AddEventHandler("main", "OnBeforeUserUpdate", Array("UserHandler", "ForgotPassword"));
/**
* Запись логов
* @param string $string строка с данными/массив
* @param string $path файл куда сохраняем
*/
function LogWriter($string, $path = "RegistrationUser")
{
$file = fopen($_SERVER['DOCUMENT_ROOT'].'/logs/'. $path .'.log', 'a+');
fwrite($file, json_encode($string, JSON_UNESCAPED_UNICODE).PHP_EOL."\t\t\t\t=========".PHP_EOL);
fclose($file);
}
$userInformation = Array();
class OrderHandler
{
function Agreement(&$arFields)
{
LogWriter($arFields, 'OrderHandler.Agreement.arFields');
LogWriter($_REQUEST, 'OrderHandler.Agreement.request');
}
}
class EmailHandler
{
function SendInvoice($ID, &$eventName, &$arFields, $val)
{
global $userInformation;
if ($userInformation['REG_NEW_USER'] == "Y"){
$arRegFields = Array(
"LOGIN" => $userInformation['arFields']['LOGIN'],
"PASSWORD" => $userInformation['arFields']['PASSWORD'],
"NAME" => $userInformation['arFields']['NAME'],
"LAST_NAME" => $userInformation['arFields']['LAST_NAME'],
"SECOND_NAME" => $userInformation['arFields']['SECOND_NAME'],
"URL_PERSONAL" => $_SERVER['HTTP_X_FORWARDED_PROTO'] . '://' . $_SERVER['HTTP_HOST']."/personal/profile/",
"EMAIL" => $userInformation['arFields']['EMAIL'],
);
CEvent::Send("NEW_USER_AUTO",'s1',$arRegFields, "N");
}
LogWriter($arFields, 'EmailHandler.SendInvoice.arFields');
LogWriter($_REQUEST, 'EmailHandler.SendInvoice.REQUEST');
LogWriter($userInformation, 'EmailHandler.SendInvoice.userInformation');
LogWriter($arRegFields, 'EmailHandler.SendInvoice.arRegFields');
$arFields["CUSTOM_FIELD_FILE"] = 'Подробнее о заказе и квитанция на оплату: ' . $_SERVER['HTTP_X_FORWARDED_PROTO'] . '://' . $_SERVER['HTTP_HOST'] . '/personal/orders/detail.php?ID=' . $ID;
}
}
class UserHandler
{
function ForgotPassword(&$arFields)
{
if ($_REQUEST['TYPE'] == "CHANGE_PWD" && $_REQUEST['AUTH_FORM'] == "Y" && $_REQUEST['change_password'] == "yes"){
global $USER;
$USER = !is_object($USER) ? new CUser : $USER;
$USER->Authorize($arFields['ID']);
}
}
function LoginCheck(&$arFields)
{
if (!preg_match("/^[a-zA-Z0-9_-]+$/", $arFields['LOGIN']) && $_REQUEST['TYPE'] != "CHANGE_PWD"){
global $APPLICATION;
$APPLICATION->throwException('Логин может состоять из латинских букв, цифр, знаков "-" и "_"');
return false;
}
}
function RequireField(&$arFields)
{
if ($_SERVER['SCRIPT_NAME'] != "/bitrix/admin/user_edit.php" && $_REQUEST['TYPE'] != "CHANGE_PWD"):
$errors = false;
global $APPLICATION;
if (!$_REQUEST['USER_SECOND_NAME'] && !$arFields['SECOND_NAME']){
$APPLICATION->throwException("Пожалуйста, введите Отчество.");
$errors = true;
}
if (!$arFields['NAME']){
$APPLICATION->throwException("Пожалуйста, введите Имя.");
$errors = true;
}
if (!$arFields['LAST_NAME']){
$APPLICATION->throwException("Пожалуйста, введите Фамилию.");
$errors = true;
}
return ($errors) ? false : true;
endif;
}
function PersonTypeOrderMake(&$arResult, &$arUserResult)
{
global $USER;
if($USER->IsAuthorized())
{
$rsUser = $USER->GetByID($USER->GetID());
$arUser = $rsUser->Fetch();
$personType = $arUser['UF_TYPE_FACE'];
//очищаем текущее значение типа плательщика
foreach($arResult['PERSON_TYPE'] as $key => $type){
if($type['CHECKED'] == 'Y'){
unset($arResult['PERSON_TYPE'][$key]['CHECKED']);
}
}
//устанавливаем новое значение типа плательщика
$arResult['PERSON_TYPE'][$personType]['CHECKED'] = 'Y';
$arUserResult['PERSON_TYPE_ID'] = $personType;
}
}
function HandlerAddSecondName(&$arFields)
{
LogWriter($arFields, "UserHandler.HandlerAddSecondName.arFields");
LogWriter($_REQUEST, "UserHandler.HandlerAddSecondName.REQUEST");
$arFields["SECOND_NAME"] = $_REQUEST['USER_SECOND_NAME'];
}
}
class GuestHandler
{
function RegistrationUser(&$arFields)
{
LogWriter($_REQUEST, "GuestHandler.RegistrationUser.REQUEST");
LogWriter($arFields, "GuestHandler.RegistrationUser.arFields");
if ($arFields['NAME'] != 'Анонимный пользователь' && $arFields['ACTIVE'] == 'Y' && $_REQUEST['TYPE'] != 'REGISTRATION'){
global $userInformation;
$fio = $_REQUEST['PERSON_TYPE'] == 2 ? $_REQUEST['ORDER_PROP_12'] : $_REQUEST['ORDER_PROP_1'];
$arFields['SECOND_NAME'] = explode(" ", $fio)[2]; // отчество
$arFields['UF_TYPE_FACE'] = $_REQUEST['PERSON_TYPE']; // Тип плательщика
$arFields['UF_INN'] = $_REQUEST['ORDER_PROP_10']; // ИНН
$arFields['UF_KPP'] = $_REQUEST['ORDER_PROP_11']; // КПП
$arFields['WORK_COMPANY'] = $_REQUEST['ORDER_PROP_8']; // Название компании
$userInformation['arFields'] = $arFields;
$userInformation['REQUEST'] = $_REQUEST;
$userInformation['REG_NEW_USER'] = "Y";
}
}
}
include_once($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/wsrubi.smtp/classes/general/wsrubismtp.php");
code.matveevs.ru
1С-Битрикс. Подписываемся на события любой сущности ORM
Почему-то в документации этот момент упущен, ну, или я просто не нашёл.
Разберём на примере сущности инфоблока — класса \Bitrix\Iblock\IblockTable.
Код обработчика для события OnBeforeAdd
Bitrix\Main\EventManager::getInstance()->addEventHandler( 'iblock', '\Bitrix\Iblock\Iblock::OnBeforeAdd', function (\Bitrix\Main\Event $e) { echo '<pre>';print_r($e->getParameters());echo '</pre>'; } );Да, всё на самом деле вот так просто :-) Единственный ньюанс — так это суффикс Table у класса, который в вызове обработчика не используется.
Список доступных событий всех сущностей:
namespace Bitrix\Main\Entity; abstract class DataManager { const EVENT_ON_BEFORE_ADD = "OnBeforeAdd"; const EVENT_ON_ADD = "OnAdd"; const EVENT_ON_AFTER_ADD = "OnAfterAdd"; const EVENT_ON_BEFORE_UPDATE = "OnBeforeUpdate"; const EVENT_ON_UPDATE = "OnUpdate"; const EVENT_ON_AFTER_UPDATE = "OnAfterUpdate"; const EVENT_ON_BEFORE_DELETE = "OnBeforeDelete"; const EVENT_ON_DELETE = "OnDelete"; const EVENT_ON_AFTER_DELETE = "OnAfterDelete";Обновлено 30.05.16
Покажу так же пример подписки на события highload-блоков. Например, наш highload-блок назван Color. Чтобы подписаться на событие, вызываемое до обновления его записи, и, запретить добавлять элементы без заполненного поля XML_ID, хватит кода:
<?php if (Bitrix\Main\Loader::includeModule('highloadblock')) { $hlColorIterator = Bitrix\Highloadblock\HighloadBlockTable::getList([ 'filter' => [ '=NAME' => 'Color' ] ]); if ($hlColor = $hlColorIterator->fetch()) { @var $colorEntity = Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlColor); Bitrix\Main\EventManager::getInstance()->addEventHandler( '', $colorEntity->getName() . 'OnBeforeUpdate', function (Bitrix\Main\Entity\Event $event) { @var $result = new Bitrix\Main\Entity\EventResult(); $data = $event->getParameter('fields'); if (!strlen(trim($data['UF_XML_ID']))) { $result->addError(new Bitrix\Main\Entity\FieldError( $event->getEntity()->getField('UF_XML_ID'), sprintf('Field "UF_XML_ID" required.') )); } return $result; } ); } }www.olegpro.ru