Система событий XOOPS
2.5.x: Preloads 4.0.x: PSR-14
Система событий XOOPS включает слабую связанность между модулями через паттерн observer. Компоненты могут инициировать события, на которые другие части системы могут подписаться и реагировать.
Типы событий
Заголовок раздела «Типы событий»События ядра
Заголовок раздела «События ядра»| Событие | Точка срабатывания |
|---|---|
core.header.start | Перед обработкой заголовка |
core.header.end | После обработки заголовка |
core.footer.start | Перед рендерингом подвала |
core.footer.end | После рендеринга подвала |
core.exception | Когда происходит исключение |
События жизненного цикла модуля
Заголовок раздела «События жизненного цикла модуля»| Событие | Точка срабатывания |
|---|---|
module.install | После установки модуля |
module.update | После обновления модуля |
module.uninstall | Перед удалением модуля |
module.activate | Когда модуль активирован |
module.deactivate | Когда модуль деактивирован |
События пользователя
Заголовок раздела «События пользователя»| Событие | Точка срабатывания |
|---|---|
user.login | После успешного входа |
user.logout | После выхода |
user.register | После регистрации |
user.delete | Перед удалением пользователя |
Система Preload (Legacy)
Заголовок раздела «Система Preload (Legacy)»Создание Preload
Заголовок раздела «Создание Preload»<?phpnamespace XoopsModules\MyModule;
use Xmf\Module\Helper\AbstractHelper;
final class Preload extends AbstractHelper{ public function eventCoreHeaderStart(array $args): void { // Запускается на каждой странице перед заголовком }
public function eventCoreFooterStart(array $args): void { // Запускается перед рендерингом подвала }
public function eventUserLogin(array $args): void { $userId = $args['userid']; // Обработать событие входа }
public function eventCoreException(array $args): void { $exception = $args['exception']; // Логировать или обработать исключение }}Именование методов события
Заголовок раздела «Именование методов события»event{Категория}{Действие}
Примеры:- eventCoreHeaderStart- eventUserLogin- eventModuleNewsArticleCreateEvent Dispatcher PSR-14 (XOOPS 4.0)
Заголовок раздела «Event Dispatcher PSR-14 (XOOPS 4.0)»Класс события
Заголовок раздела «Класс события»<?php
declare(strict_types=1);
namespace XoopsModules\MyModule\Event;
final class ArticleCreatedEvent{ public function __construct( public readonly int $articleId, public readonly int $authorId, public readonly string $title, public readonly \DateTimeImmutable $createdAt ) {}}Диспетчеризация событий
Заголовок раздела «Диспетчеризация событий»use Psr\EventDispatcher\EventDispatcherInterface;
final class ArticleService{ public function __construct( private readonly ArticleRepository $repository, private readonly EventDispatcherInterface $dispatcher ) {}
public function create(CreateArticleDTO $dto): Article { $article = Article::create($dto); $this->repository->save($article);
// Диспетчеризировать событие $this->dispatcher->dispatch(new ArticleCreatedEvent( articleId: $article->getId(), authorId: $article->getAuthorId(), title: $article->getTitle(), createdAt: new \DateTimeImmutable() ));
return $article; }}Слушатель события
Заголовок раздела «Слушатель события»<?php
declare(strict_types=1);
namespace XoopsModules\MyModule\Listener;
use XoopsModules\MyModule\Event\ArticleCreatedEvent;
final class SendNotificationOnArticleCreated{ public function __construct( private readonly NotificationService $notifications ) {}
public function __invoke(ArticleCreatedEvent $event): void { $this->notifications->notifySubscribers( 'new_article', [ 'article_id' => $event->articleId, 'title' => $event->title, ] ); }}Регистрация слушателей
Заголовок раздела «Регистрация слушателей»return [ ArticleCreatedEvent::class => [ SendNotificationOnArticleCreated::class, UpdateSearchIndex::class, ClearArticleCache::class, ],
ArticleUpdatedEvent::class => [ UpdateSearchIndex::class, ClearArticleCache::class, ],
ArticleDeletedEvent::class => [ RemoveFromSearchIndex::class, ClearArticleCache::class, ],];События, которые можно остановить
Заголовок раздела «События, которые можно остановить»use Psr\EventDispatcher\StoppableEventInterface;
final class ArticlePublishingEvent implements StoppableEventInterface{ private bool $propagationStopped = false; private ?string $rejectionReason = null;
public function __construct( public readonly Article $article ) {}
public function isPropagationStopped(): bool { return $this->propagationStopped; }
public function reject(string $reason): void { $this->propagationStopped = true; $this->rejectionReason = $reason; }
public function getRejectionReason(): ?string { return $this->rejectionReason; }}
// Слушатель может остановить распространениеfinal class ContentModerationListener{ public function __invoke(ArticlePublishingEvent $event): void { if ($this->containsProhibitedContent($event->article)) { $event->reject('Content violates community guidelines'); } }}Лучшие практики
Заголовок раздела «Лучшие практики»- Неизменяемые события - события должны быть только для чтения
- Специфичные события - создавайте конкретные события, не общие
- Асинхронность, когда возможно - используйте очереди для медленных операций
- Без побочных эффектов при диспетчеризации - диспетчеризация должна быть быстрой
- Документируйте события - перечисляйте доступные события для пользователей модуля
Связанная документация
Заголовок раздела «Связанная документация»- Разработка модулей - Разработка модулей
- Event-System-Guide - Руководство PSR-14
- Hooks-Events - Legacy hooks
- Events-and-Hooks - Примеры событий