Документация

PHP-события

Модуль отправляет собственные события D7 от имени модуля slytek.skyshop. Обработчики позволяют менять данные и добавлять функции, не трогая код модуля и шаблона, — такие доработки не теряются при обновлениях и синхронизации шаблона.

Как подписаться

Обработчики регистрируются стандартным менеджером событий «Битрикса», обычно в файле /local/php_interface/init.php:

<?php
use Bitrix\Main\Event;
use Bitrix\Main\EventManager;
use Bitrix\Main\EventResult;

$eventManager = EventManager::getInstance();

$eventManager->addEventHandler('slytek.skyshop', 'onBeforeBasketAdd', function (Event $event) {
    $product = $event->getParameters();

    // ...меняем данные...

    return new EventResult(EventResult::SUCCESS, $product);
});

Вместо анонимной функции можно указать метод своего класса: [\My\Project\SkyshopHandlers::class, 'onBeforeBasketAdd'].

Как модуль применяет ответ обработчика

РежимЧто происходит с ответомСобытия
ИзменениеОтвет сливается с исходными данными через array_replace_recursive. Достаточно вернуть только изменённые ключи.onBuildSettingsList, onLoadSettingsValues, onBeforeBasketAdd, onAjaxData
ЗаменаНепустой массив из ответа целиком заменяет результат. Пустой ответ ничего не меняет.onAjaxResult
ШаблонКлючи arResult и arParams из ответа заменяют соответствующие массивы компонента.onBeforeTemplateModify, onAfterTemplateModify
КонтентСтроки из ответов всех обработчиков склеиваются и выводятся на страницу.onContent…

Список событий

СобытиеКогда вызываетсяПараметры
onBuildSettingsListПри построении списка настроек: страница настроек, панель «Настройки темы», чтение значенийМассив описаний всех настроек
onLoadSettingsValuesПри загрузке сохранённых значений настроек, один раз за запросМассив всех значений
onBeforeBasketAddПеред добавлением товара в корзину кнопками шаблонаPRODUCT_ID, QUANTITY, PROPS
onAjaxDataПеред обработкой AJAX-запроса шаблонаМассив действий: 'cart:add' => параметры
onAjaxResultПосле выполнения каждого AJAX-действияtype, params, result
onBeforeTemplateModifyВ result_modifier.php шаблонов SkyShop до обработки данных модулемarResult, arParams, name, template, component
onAfterTemplateModifyТо же, после обработки данных модулемТе же
onContentProductDetail…В точках вывода карточки товараTYPE, arResult, arParams

onBuildSettingsList — свои настройки

Событие получает описание всех настроек (структура как в /bitrix/modules/slytek.skyshop/data/options.php). Добавьте свои поля или вкладки — они появятся на странице настроек сайта, будут сохраняться вместе с остальными и читаться через Settings::get().

$eventManager->addEventHandler('slytek.skyshop', 'onBuildSettingsList', function (Event $event) {
    return new EventResult(EventResult::SUCCESS, [
        // новая вкладка на странице настроек
        'promo' => [
            'name'  => 'Промо',
            'type'  => 'tab',
            'items' => [
                'on'    => ['name' => 'Показывать промо-блок', 'type' => 'checkbox', 'constructor' => true],
                'title' => ['name' => 'Заголовок'],
                'text'  => ['name' => 'Текст', 'type' => 'html'],
                'image' => ['name' => 'Картинка', 'type' => 'image'],
            ],
        ],
    ]);
});

Чтение значения в любом месте сайта:

use Bitrix\Main\Loader;
use Slytek\Skyshop\Settings;

Loader::includeModule('slytek.skyshop');

if (Settings::get('promo->on') === 'Y') {
    echo Settings::get('promo->title');
}

// встроенные настройки читаются так же
$phone = Settings::get('contacts->phone');
$showStock = Settings::get('catalog->available->on');

Путь к значению записывается через ->. Второй аргумент Settings::get() — код сайта; по умолчанию берётся текущий.

Типы полей

ТипПоле в настройках
не указанОднострочное текстовое поле.
checkboxГалочка, значение Y или N.
textМногострочное поле.
htmlВизуальный редактор.
imageЗагрузка картинки, значение — путь к файлу.
radio, selectВыбор из списка values: ['code' => ['value' => 'code', 'name' => 'Название']]. С флагом 'multiple' => true можно выбрать несколько.
colorpickerВыбор цвета.
iblock, property, element, price, form, agreementСписки из данных сайта: инфоблоки, свойства, элементы, типы цен, веб-формы, соглашения. Источник задаётся ключом source, например 'source' => 'catalog' для свойств каталога.
tabВкладка; её поля перечисляются в items. Группа полей без вкладки — элемент с items без type.
ФлагЧто делает
constructorПоказывать поле в панели «Настройки темы» на сайте. Для полей внутри групп флаг нужен и у группы.
sortableПоля группы можно перетаскивать, порядок сохраняется.
css-variablesЗначение выводится как CSS-переменная на :root; имя переменной — код поля, где подчёркивания заменены дефисами. У вариантов radio вместо этого можно задать свой набор переменных ключом variables.

onLoadSettingsValues — подмена значений

Срабатывает, когда модуль загружает сохранённые значения. Верните изменённые ключи, чтобы подменить настройки «на лету», не сохраняя их. Например, свой телефон для оптового домена:

$eventManager->addEventHandler('slytek.skyshop', 'onLoadSettingsValues', function (Event $event) {
    if (defined('ADMIN_SECTION')) {
        return; // не подменяем в админке, иначе подмена сохранится в настройки
    }
    if ($_SERVER['HTTP_HOST'] === 'opt.example.ru') {
        return new EventResult(EventResult::SUCCESS, [
            'contacts' => ['phone' => '+7 (495) 000-00-00'],
        ]);
    }
});
!
Страница настроек в админке загружает значения через то же событие. Без проверки ADMIN_SECTION подменённые значения попадут в форму и сохранятся в файл при нажатии «Сохранить».

onBeforeBasketAdd — перед добавлением в корзину

Вызывается, когда покупатель добавляет товар кнопками шаблона. Параметры — данные будущей позиции корзины: PRODUCT_ID, QUANTITY и PROPS — свойства позиции (массивы с ключами NAME, CODE, VALUE).

$eventManager->addEventHandler('slytek.skyshop', 'onBeforeBasketAdd', function (Event $event) {
    $product = $event->getParameters();

    // добавляем к позиции свойство с меткой источника
    $product['PROPS'][] = [
        'NAME'  => 'Источник',
        'CODE'  => 'SOURCE',
        'VALUE' => 'Сайт',
    ];

    return new EventResult(EventResult::SUCCESS, $product);
});

onAjaxData — перед AJAX-запросом

Все AJAX-действия шаблона (корзина, избранное, сравнение, формы, подгрузка блоков) приходят на сервер одним запросом в виде массива 'тип:действие' => параметры, например 'cart:add' или 'favorite:trigger'. Событие получает этот массив до обработки: можно изменить параметры, добавить или убрать действия.

$eventManager->addEventHandler('slytek.skyshop', 'onAjaxData', function (Event $event) {
    $actions = $event->getParameters();

    if (isset($actions['compare:clear'])) {
        \Bitrix\Main\Diag\Debug::writeToFile('Пользователь очистил сравнение');
    }
});

Ответ обработчика сливается с исходным массивом, поэтому через это событие можно изменить параметры или добавить действие, но не убрать его. Чтобы отменить действие, используйте JS-событие data::<действие>.

onAjaxResult — после AJAX-действия

Срабатывает для каждого действия после его выполнения. Параметры: type — ключ действия, params — его параметры, result — результат. Если обработчик вернёт непустой массив, он полностью заменит результат.

Так удобно делать свои AJAX-действия без отдельного обработчика запросов. На странице — кнопка с атрибутом data-ajaxaction:

<button type="button" class="btn" data-ajaxaction="promo:coupon" data-params='{"code":"SPRING"}'>
    Получить купон
</button>

На сервере — обработчик, который отвечает только на своё действие:

$eventManager->addEventHandler('slytek.skyshop', 'onAjaxResult', function (Event $event) {
    if ($event->getParameter('type') !== 'promo:coupon') {
        return; // чужие действия не трогаем
    }
    $params = $event->getParameter('params'); // ['code' => 'SPRING']

    return new EventResult(EventResult::SUCCESS, [
        'success' => true,
        'message' => 'Ваш купон: ' . htmlspecialcharsbx($params['code']),
    ]);
});

Если в ответе есть message, шаблон сам покажет его во всплывающем окне: при success: true — как сообщение об успехе, иначе — как ошибку. Ответ доступен и в JS-событии AjaxHandler | action.

i
Используйте префикс, которого нет у шаблона (promo:, mycompany:), чтобы ваши действия не пересекались со встроенными cart:, favorite:, compare:.

onBeforeTemplateModify и onAfterTemplateModify — данные компонентов

Вызываются в result_modifier.php шаблонов SkyShop: списки и детальные страницы инфоблоков, каталог и разделы, умный фильтр, корзина. onBeforeTemplateModify срабатывает до того, как модуль подготовит данные, onAfterTemplateModify — после.

ПараметрЧто содержит
arResultРезультат компонента.
arParamsПараметры компонента.
nameИмя компонента, например bitrix:catalog.section.
templateИмя шаблона компонента.
componentОбъект компонента.
$eventManager->addEventHandler('slytek.skyshop', 'onAfterTemplateModify', function (Event $event) {
    if ($event->getParameter('name') !== 'bitrix:catalog.section') {
        return;
    }
    $arResult = $event->getParameter('arResult');

    // не показываем в списках товары без картинок
    foreach ($arResult['ITEMS'] as $key => $item) {
        if (empty($item['PREVIEW_PICTURE']) && empty($item['DETAIL_PICTURE'])) {
            unset($arResult['ITEMS'][$key]);
        }
    }

    return new EventResult(EventResult::SUCCESS, ['arResult' => $arResult]);
});
!
Результат кешируется
result_modifier.php выполняется внутри кеша компонента, поэтому изменения кешируются вместе с ним. Не добавляйте сюда данные, зависящие от пользователя, и сбрасывайте кеш после правки обработчика.

onContent… — свой HTML в карточке товара

В карточке товара есть точки, куда можно вывести свой HTML без правки шаблона. Имя события — onContent плюс название точки:

СобытиеГде выводится
onContentProductDetailAfterTitleПод названием товара
onContentProductDetailAfterPriceПод ценой
onContentProductDetailBeforeButtonsПеред кнопками покупки
onContentProductDetailAfterButtonsПосле кнопок покупки

Параметры: TYPE — название точки, arResult и arParams карточки товара. Обработчик возвращает строку HTML.

$eventManager->addEventHandler('slytek.skyshop', 'onContentProductDetailAfterPrice', function (Event $event) {
    $arResult = $event->getParameter('arResult');
    $weight = $arResult['PROPERTIES']['WEIGHT']['VALUE'] ?? '';

    if ($weight === '') {
        return;
    }
    return new EventResult(
        EventResult::SUCCESS,
        '<div class="product-note">Вес: ' . htmlspecialcharsbx($weight) . '</div>'
    );
});

Вывод кешируется вместе с карточкой товара, как и в событиях шаблонов.

Какие стандартные события обрабатывает модуль

Справочно — чтобы ваши обработчики не конфликтовали с модулем:

МодульСобытиеЧто делает SkyShop
mainOnPageStart, OnBeforeProlog, OnEpilogПодготовка страницы, обработка AJAX-запросов шаблона, вывод служебных данных
mainOnAfterUserAdd, OnAfterUserUpdateПодписка на рассылку по галочке согласия
saleOnSaleOrderBeforeSavedПроверка минимальной суммы заказа
saleOnSaleComponentOrderPropertiesЗаполнение свойств заказа
saleOnSaleOrderSavedПодписка на рассылку из оформления заказа
catalogProduct::OnAfterAdd, Product::OnAfterUpdateОбновление служебного свойства наличия у товара
catalogOnGetOptimalPriceЦены по типу цен выбранного города
iblockOnIBlockPropertyBuildListСвои типы свойств: тип цены, склад, местоположение