Предложение нового механизма closure и слушателей событий в bootstrap неймспейсов MODX с приоритетами и именами
Хочу поделиться идеей/потенциальным изменением ядра MODX 3, которое даст возможность создавать пакеты без плагинов, да и в целом расширить функционал управления слушателями событий, и попросить вас посмотреть, что думаете.
Началось с того, что я пытаюсь продумать для себя максимально простой способ разработки и сборки пакетов под MODX, и параллельно внедрения архитектурных решений по стилю Laravel.
В процессе пришла идея «а зачем создавать плагины в пакете, если сейчас MODX 3 подключает bootstrap.php файл расширения, и по сути мы в этом бутстрапе можем зарегистрировать слушателей событий без плагинов вовсе».
Для этого так кстати есть метод
Попробовал и обнаружил забавный нюанс — в бутстрап addEventListener работать по сути не будет, поскольку подключение бустрапов происходит ДО основной загрузки карты событий, и эта карта перезатирается потом полностью.
Даже если мы пойдем дальше и в бутстрапе попробуем обхитрить MODX, заранее создав карту:
Проблема как таковая останется, потому что вроде как плагин должен при отсутствии в кеше браться из базы данных напрямую, но почему то у меня так не сработало, возможно это ошибка в логике получения плагина из бд, в которой ковыряться не очень хочется. Поэтому решил посмотреть, как это реализовано в ядре modX.php.
Собственно немного там поковыряв, получилось такое решение — пулл-реквест на гитхабе.
Пример тестирования достаточно подробно описан в пулл-реквесте, меняется там только modX файл — предлагается просто закинуть его в проект-черновик и потестить.
Хотелось бы обратную связь сообщества:
Началось с того, что я пытаюсь продумать для себя максимально простой способ разработки и сборки пакетов под MODX, и параллельно внедрения архитектурных решений по стилю Laravel.
В процессе пришла идея «а зачем создавать плагины в пакете, если сейчас MODX 3 подключает bootstrap.php файл расширения, и по сути мы в этом бутстрапе можем зарегистрировать слушателей событий без плагинов вовсе».
Для этого так кстати есть метод
$modx->addEventListener Попробовал и обнаружил забавный нюанс — в бутстрап addEventListener работать по сути не будет, поскольку подключение бустрапов происходит ДО основной загрузки карты событий, и эта карта перезатирается потом полностью.
Даже если мы пойдем дальше и в бутстрапе попробуем обхитрить MODX, заранее создав карту:
if ($modx->eventMap === null) {
$modx->eventMap = $modx->getEventMap('web');
}
$modx->addEventListener('OnWebPagePrerender', 33); Проблема как таковая останется, потому что вроде как плагин должен при отсутствии в кеше браться из базы данных напрямую, но почему то у меня так не сработало, возможно это ошибка в логике получения плагина из бд, в которой ковыряться не очень хочется. Поэтому решил посмотреть, как это реализовано в ядре modX.php.
Собственно немного там поковыряв, получилось такое решение — пулл-реквест на гитхабе.
- Возможность добавлять runtime-события через addEventListener(), которые живут в отдельном свойстве $modx и не затираются при инициализации eventMap() из БД.
- 🔥 Новый метод addEventListenerClosure(...) — чтобы навешивать слушатели-замыканя (closures) с указанием приоритета и имени.
- Универсальный метод удаления removeEventListenerClosure(...), который позволяет удалять слушателей по событию, приоритету или имени, либо глобально.
- Всё сделано с сохранением обратной совместимости, чтобы плагины и существующие события продолжали работать как раньше.
Пример тестирования достаточно подробно описан в пулл-реквесте, меняется там только modX файл — предлагается просто закинуть его в проект-черновик и потестить.
Хотелось бы обратную связь сообщества:
- Насколько вы считаете эту идею полезной?
- Есть ли юз-кейсы, которые не покрываются предлагаемой схемой?
- Какие риски или неудобства видите? (например, производительность, совместимость, сложность).
- Есть ли предложения, как сделать API ещё удобнее?
- ...
Комментарии: 8
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
видимо, управлять приоритетом можно.
И после просмотра примера возник новый вопрос: а если у меня будет большая функция или несколько функций или я хочу использовать целый класс в плагине, как тогда?
Проблема в том что карта у них строится без какой либо доп информации о плагинах, просто событие->список ID плагинов, уже отсортированных в sql запросе. То есть пересортировать ее без дополнительного запроса к базе не получится (ну или надо сохранять расширенную карту из базы при инициализации и потом при добавлении нового плагина пересобирать итоговую карту). Сейчас реализовано так, что сначала выполняются плагины из бд — и подвязанные к событию в админке, и подвязанные к событию в коде, потом все closure плагины. Вообще это больше не для того чтобы кто-то в админке вручную тыкал, а чтобы например при разработке пакета вы спокойно свой функционал раскидали по нужным событиям и не парились с созданием плагинов и привязкой/отвязкой событий при обновлении например.