cloud-castle / event
Самый функциональный и быстрый PSR-14 диспетчер событий для PHP 8.1+: приоритеты, порядок before/after с топосортировкой, иерархия типов, именованные и wildcard-события, атрибуты, ленивые сервисы, отладочный и буферизующий диспетчеры, компиляция провайдера. Зависимости — только PSR.
Requires
- php: >=8.1
- psr/container: ^1.1 || ^2.0
- psr/event-dispatcher: ^1.0
- psr/log: ^1.1 || ^2.0 || ^3.0
Requires (Dev)
- crell/tukio: ^2.0
- deptrac/deptrac: ^3.0 || ^4.0
- ergebnis/composer-normalize: ^2.45
- friendsofphp/php-cs-fixer: ^3.75
- icanhazstring/composer-unused: ^0.9
- infection/infection: ^0.29 || ^0.33
- league/event: ^3.0
- phly/phly-event-dispatcher: ^1.4
- php-parallel-lint/php-parallel-lint: ^1.4
- phpmd/phpmd: ^2.15
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^1.12 || ^2.1
- phpstan/phpstan-deprecation-rules: ^1.2 || ^2.0
- phpstan/phpstan-phpunit: ^1.4 || ^2.0
- phpstan/phpstan-strict-rules: ^1.6 || ^2.0
- phpunit/phpunit: ^10.5 || ^11.5
- psalm/plugin-phpunit: ^0.19 || ^0.20
- rector/rector: ^1.2 || ^2.0
- roave/security-advisories: dev-latest
- squizlabs/php_codesniffer: ^3.12 || ^4.0
- symfony/event-dispatcher: ^6.4 || ^7.0
- vimeo/psalm: ^6.0
- webmozart/assert: ^1.11
- yiisoft/event-dispatcher: ^1.1
Suggests
None
Provides
Conflicts
None
Replaces
None
README
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
CloudCastle Event
Самый функциональный и быстрый PSR-14 диспетчер событий для PHP 8.1+: приоритеты, порядок before/after с топологической сортировкой, подписка по иерархии типов, именованные и wildcard-события, регистрация через атрибуты, ленивые слушатели-сервисы, интроспекция, отладочный и буферизующий диспетчеры, компиляция провайдера. Зависимости — только PSR (
psr/event-dispatcher,psr/container,psr/log).
Установка
composer require cloud-castle/event
Требуется PHP 8.1+. Рекомендуемое ограничение версии: ^2.0.
Быстрый старт
<?php
use CloudCastle\Event\EventDispatcher;
use CloudCastle\Event\ListenerProvider;
use CloudCastle\Event\Priority;
final class OrderPlaced
{
public function __construct(public readonly int $orderId)
{
}
}
$provider = new ListenerProvider();
// Приоритет: больше — раньше (Priority::HIGH/NORMAL/LOW или любое int).
$provider->listen(OrderPlaced::class, static function (OrderPlaced $event): void {
// отправить уведомление по $event->orderId
}, Priority::HIGH);
// Тип события можно вывести из подсказки типа слушателя.
$provider->listenInferred(static function (OrderPlaced $event): void {
// записать в аудит
});
// Одноразовый слушатель; снятие по возвращённому идентификатору.
$id = $provider->listenOnce(OrderPlaced::class, static fn (OrderPlaced $e) => null);
$provider->remove($id);
$dispatcher = new EventDispatcher($provider);
$event = $dispatcher->dispatch(new OrderPlaced(42));
Порядок before/after, wildcard, именованные события, ленивые сервисы и декораторы диспетчера — в документации и на wiki (страница на каждую возможность).
Возможности
Ядро
- PSR-14
EventDispatcher+ListenerProvider— совместимость с любым потребителем. - Приоритеты слушателей (
Priority::HIGH/NORMAL/LOW), стабильный порядок при равенстве. - Порядок before/after с топологической сортировкой и детекцией циклов.
- Иерархия типов — слушатель на класс, родителя или интерфейс события.
- Именованные/строковые события (
NamedEventInterface) и wildcard (*). - Псевдонимы типов событий.
- Автоопределение типа события из подсказки типа слушателя (включая union).
- Одноразовые слушатели, снятие по id, снятие всех типа, подписчики, снятие подписчика.
- Интроспекция:
getListeners(),hasListeners(),getListenerPriority(). - Кэш разрешения слушателей — быстрый горячий путь.
Регистрация и DI
- Атрибуты
#[Listener]+AttributeListenerRegistrar. - Ленивые слушатели-сервисы из PSR-11 контейнера (
listenService).
Диспетчеры (декораторы)
- Logging (PSR-3) с изоляцией ошибок слушателей (fail-safe).
- Traceable — статистика вызванных/осиротевших событий.
- Buffered — отложенная рассылка пачкой.
- Composite — цепочка диспетчеров.
Провайдеры
- Composite, Delegating (по типу), Callback (по субъекту), Immutable (read-only), Compiled (заранее разрешённые списки).
События и утилиты
- StoppableEvent / StoppableEventTrait, GenericEvent (субъект+аргументы), трейты RecordsEvents (агрегаты) и DispatchesEvents (сервисы).
Сравнение с аналогами
Все таблицы ниже сгенерированы автоматически из честных сравнительных
тестов (benchmarks/compare.php) на ОДИНАКОВОЙ операции для всех аналогов,
PHP 8.3.33, без Xdebug.
1. Функциональность
| Возможность | 🏆 CloudCastle | symfony | league | tukio | yiisoft | phly | manual¹ |
|---|---|---|---|---|---|---|---|
| PSR-14 совместимость (dispatch/StoppableEvent) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Приоритеты слушателей | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Подписка по иерархии типов (родители/интерфейсы) | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Именованные/строковые события | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Wildcard-слушатели (на любое событие) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Порядок before/after + топосортировка | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Регистрация через атрибуты | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Ленивые слушатели-сервисы (PSR-11) | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
| Одноразовые слушатели | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Подписчики | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Интроспекция (getListeners/priority) | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Debug/Traceable-диспетчер | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Буферизация (отложенная рассылка) | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Скомпилированный провайдер | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Автоопределение типа из подсказки (+union) | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ |
| Всего | 🏆 15 | 8 | 7 | 10 | 3 | 5 | 0 |
2. Безопасность и корректность
| Свойство | 🏆 CloudCastle | symfony | league | tukio | yiisoft | phly | manual¹ |
|---|---|---|---|---|---|---|---|
| Иммутабельная регистрация (нет глобального состояния) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Остановка распространения (StoppableEventInterface) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Детерминированный порядок слушателей (приоритеты) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Изоляция ошибок слушателя (не рушит остальные) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Типобезопасная маршрутизация по типу события | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Всего | 🏆 5 | 4 | 4 | 4 | 3 | 4 | 0 |
3. Качество кода
_Прогон СОБСТВЕННЫХ инструментов проекта (PHPStan max, Psalm errorLevel 1, PHPMD, PHPCodeSniffer PSR-12, Rector, Deptrac) ЕДИНЫМ строгим конфигом по исходникам каждой библиотеки. Меньше замечаний — код строже проходит без исключений (у каждого проекта свои настройки анализа). Deptrac (архитектурные слои) и мутационное MSI (тесты не входят в дистрибутив) измеримы только для самого пакета — для аналогов «н/д»..
| Проверка | CloudCastle | symfony | league | tukio | yiisoft | phly | 🏆 Победитель |
|---|---|---|---|---|---|---|---|
| phplint (синтаксис) | 0 | 0 | 0 | 0 | 0 | 0 | ничья |
| PHPStan (level max) | 0 | 229 | 8 | 65 | 2 | 39 | 🏆 CloudCastle |
| Psalm (errorLevel 1) | 0 | 0 | 0 | 0 | 0 | 0 | ничья |
| PHPMD | 0 | 55 | 2 | 8 | 1 | 4 | 🏆 CloudCastle |
| PHP_CodeSniffer (PSR-12) | 0 | 45 | 8 | 45 | 0 | 0 | 🏆 CloudCastle, yiisoft, phly |
| Rector (dry-run) | 0 | 10 | 5 | 9 | 3 | 9 | 🏆 CloudCastle |
| Deptrac (слои) | 0 | н/д | н/д | н/д | н/д | н/д | 🏆 CloudCastle |
| Мутационное (MSI) | 100 | н/д | н/д | н/д | н/д | н/д | 🏆 CloudCastle |
| Итого замечаний | 🏆 0 | 339 | 23 | 127 | 6 | 52 | 🏆 CloudCastle |
4. Производительность
Рассылка события одному слушателю, 1 000 000 раз (минимум из 10).
| Решение | Время (мс) | 🏆 Победитель |
|---|---|---|
| manual¹ | 84,7 | базовый уровень (не библиотека) |
| 🏆 CloudCastle | 197,7 | быстрейшее среди библиотек |
| symfony | 226,1 | — |
| league | 475,2 | — |
| phly | 710,4 | — |
| tukio | 773 | — |
| yiisoft | 1 101,1 | — |
5. Потребление памяти
Память, удерживаемая библиотекой в сценарии рассылки (изолированный процесс, дельта к baseline).
| Решение | Пиковая память (KB) | 🏆 Победитель |
|---|---|---|
| manual¹ | 1 | базовый уровень (не библиотека) |
| 🏆 phly | 14 | легчайшее среди библиотек |
| yiisoft | 19 | — |
| league | 29 | — |
| symfony | 40 | — |
| CloudCastle | 85 | — |
| tukio | 336 | — |
6. Утечки памяти
Рост памяти за 500 000 рассылок после прогрева (изолированный процесс; 0 — нет утечки, меньше — лучше).
| Решение | Утечки памяти (байт) | 🏆 Победитель |
|---|---|---|
| 🏆 CloudCastle | 0 | 🏆 без утечки |
| 🏆 symfony | 0 | 🏆 без утечки |
| 🏆 league | 0 | 🏆 без утечки |
| 🏆 tukio | 0 | 🏆 без утечки |
| 🏆 yiisoft | 0 | 🏆 без утечки |
| 🏆 phly | 0 | 🏆 без утечки |
| manual¹ | 0 | базовый уровень (не библиотека) |
¹ Базовый уровень (нативные вызовы/примитивы без полноты решения) показан для контекста и не претендует на победу среди библиотек-аналогов.
Ручной массив слушателей (baseline) быстрее, но без приоритетов, иерархии типов, одноразовых слушателей, подписчиков и остановки распространения. Память измеряется в изоляции (только целевая библиотека в процессе).
Плюсы и минусы
Плюсы
- Функционал — суперсет возможностей symfony, league, tukio и yiisoft вместе взятых, плюс wildcard-слушатели, которых нет ни у одного из них.
- Быстрейший среди PSR-14 библиотек на горячем пути (кэш разрешения).
- Безопасность и корректность: детерминированный порядок, изоляция ошибок слушателя, детекция циклов before/after, отсутствие глобального состояния.
- Строгое качество: PHPStan max, Psalm errorLevel 1, PHPMD, Deptrac, Rector, PSR-12; покрытие 100% и Infection MSI 100%; матрица PHP 8.1–8.5.
- Только PSR-зависимости (
psr/event-dispatcher,psr/container,psr/log).
Минусы
- Моложе и менее распространён, чем symfony/league — меньше звёзд и установок.
- Потребление памяти выше, чем у минималистичных yiisoft/league: это сознательный компромисс — богатый набор возможностей загружает больше классов. Память — единственный критерий, которым мы жертвуем ради функционала, производительности и безопасности; если нужен минимальный след и только базовая рассылка — минималистичная библиотека будет легче.
Рекомендации по применению
- Приложения и фреймворки со сложной маршрутизацией событий (приоритеты, before/after, иерархия типов, wildcard) — основной сценарий CloudCastle Event.
- Модульные/плагинные системы — композитные и делегирующие провайдеры, подписчики и атрибуты упрощают сборку слушателей из разных источников.
- Финтех/критичные домены — изоляция ошибок слушателей (fail-safe) и журналирование PSR-3 не дают одному сбойному обработчику ронять операцию.
- Высоконагруженный прод — скомпилированный провайдер и кэш разрешения дают максимум скорости; отладочный диспетчер помогает в разработке.
- Отложенные эффекты (после коммита транзакции) — буферизующий диспетчер.
- Если нужен минимальный след памяти и только простая рассылка — рассмотрите более лёгкую библиотеку; выигрыш CloudCastle раскрывается на богатых сценариях.
Разработка
composer install
composer check # линтеры + статический анализ + тесты
composer fix # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci # полный CI-пайплайн локально
Полный список команд с описаниями: composer run-script --list.
Документация
- Репозиторий: https://gitverse.ru/cloud-castle/event
- История изменений: CHANGELOG.md
- Как внести вклад: CONTRIBUTING.md
- Кодекс поведения: CODE_OF_CONDUCT.md
- Политика безопасности: SECURITY.md
Лицензия
MIT © CloudCastle (alex-4-17@yandex.ru)
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano