コンテンツにスキップ

XOOPS イベントシステム

2.5.x: Preloads 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 “プリロードシステム(レガシー)”
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{Category}{Action}
例:
- eventCoreHeaderStart
- eventUserLogin
- eventModuleNewsArticleCreate

PSR-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,
]
);
}
}
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. イベントを文書化 - モジュールユーザー用に利用可能なイベントをリスト