XOOPS 事件系統
2.5.x: 預加載 4.0.x: PSR-14
XOOPS 事件系統透過觀察者模式實現模組之間的鬆散耦合。元件可以發出其他部分系統可以偵聽和回應的事件。
| 事件 | 觸發點 |
|---|---|
core.header.start | 頁首處理前 |
core.header.end | 頁首處理後 |
core.footer.start | 頁尾呈現前 |
core.footer.end | 頁尾呈現後 |
core.exception | 發生異常時 |
模組生命週期事件
Section titled “模組生命週期事件”| 事件 | 觸發點 |
|---|---|
module.install | 模組安裝後 |
module.update | 模組更新後 |
module.uninstall | 模組移除前 |
module.activate | 啟用模組時 |
module.deactivate | 停用模組時 |
| 事件 | 觸發點 |
|---|---|
user.login | 成功登錄後 |
user.logout | 登出後 |
user.register | 註冊後 |
user.delete | 使用者刪除前 |
預加載系統 (舊版)
Section titled “預加載系統 (舊版)”<?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']; // 記錄或處理異常 }}事件方法命名
Section titled “事件方法命名”event{Category}{Action}
示例:- eventCoreHeaderStart- eventUserLogin- eventModuleNewsArticleCreatePSR-14 事件發派器 (XOOPS 4.0)
Section titled “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'); } }}- 不可變事件 - 事件應該是唯讀的
- 特定事件 - 建立特定事件,而不是通用事件
- 盡可能非同步 - 使用佇列進行緩慢操作
- 發派中無副作用 - 發派應該很快
- 記錄事件 - 為模組使用者列出可用事件