Перейти к содержимому

Система событий 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Перед удалением пользователя
class/Preload.php
<?php
namespace 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
- eventModuleNewsArticleCreate
<?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,
]
);
}
}
config/events.php
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');
}
}
}
  1. Неизменяемые события - события должны быть только для чтения
  2. Специфичные события - создавайте конкретные события, не общие
  3. Асинхронность, когда возможно - используйте очереди для медленных операций
  4. Без побочных эффектов при диспетчеризации - диспетчеризация должна быть быстрой
  5. Документируйте события - перечисляйте доступные события для пользователей модуля