跳转到内容

“XOOPS事件系统”

2.5.x:预加载 4.0.x:PSR-14

:::注意[不确定使用哪个事件系统?] 请参阅Choosing an Event System,了解决策树以及两种方法的代码示例。 :::

XOOPS事件系统通过观察者模式实现模区块之间的松散耦合。组件可以发出系统其他部分可以侦听和响应的事件。

活动触发点
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
{
// Runs on every page before header
}
public function eventCoreFooterStart(array $args): void
{
// Runs before footer renders
}
public function eventUserLogin(array $args): void
{
$userId = $args['userid'];
// Handle login event
}
public function eventCoreException(array $args): void
{
$exception = $args['exception'];
// Log or handle exception
}
}
event{Category}{Action}
Examples:
- 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);
// Dispatch event
$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;
}
}
// Listener can stop propagation
final class ContentModerationListener
{
public function __invoke(ArticlePublishingEvent $event): void
{
if ($this->containsProhibitedContent($event->article)) {
$event->reject('Content violates community guidelines');
}
}
}
  1. 不可变事件 - 事件应阅读-only
  2. 特定事件 - 创建特定事件,而不是通用事件
  3. 尽可能异步 - 使用队列进行慢速操作
  4. 调度无副作用 - 调度应该很快
  5. 文档事件 - 列出模区块用户可用的事件