フックとプラグイン開発
WordPress スタイルのアクション・フィルターフックシステムで TubePress を拡張しましょう。15 以上のフックポイント、プラグインのライフサイクル、そして独自プラグインの作成とパッケージ化の方法を解説します。
プラグインは、コアに手を加えずに TubePress に機能を追加する手段です。プラグインは、小規模な WordPress スタイルのシステムを通じて CMS にフックします。そのシステムは アクション(撃ちっぱなしのイベント)と フィルター(値を受け取り変更して返す)で構成されています。バンドルされている 3 つのプラグイン — Age Gate、Backup Pro、CTR Ranking — は、ここに記載された同じ API だけで構築されています。
フックシステム
静的クラス HookSystem は両種類のフックを管理します。コールバックは優先度の昇順(デフォルト 10)で実行されます。コールバックがスローした例外はキャッチされてログに記録されるため、不良プラグイン 1 つでページ全体がダウンすることはありません。
// Actions — do something when an event fires
HookSystem::addAction('head.meta', function () {
echo '<meta name="rating" content="adult">';
}, 10);
// Filters — receive a value, return a (possibly) changed value
HookSystem::addFilter('theme.template_data', function ($data, $template) {
if ($template === 'home') {
$data['promo'] = Promo::current();
}
return $data;
});| メソッド | 目的 |
|---|---|
addAction($hook, $cb, $priority = 10) | アクションリスナーを登録する。 |
doAction($hook, ...$args) | アクションを発火する(コアが呼び出す)。 |
addFilter($hook, $cb, $priority = 10) | フィルターを登録する。 |
applyFilter($hook, $value, ...$args) | 値をフィルターに通して返す。 |
hasAction() / hasFilter() | リスナーが存在するか確認する。 |
removeAction() / removeFilter() | フックのリスナーをすべて取り外す。 |
利用可能なフックポイント
コアはこれらのフックを発火します。プラグインから独自のフックを定義して発火することもできます。
アクション
| フック | 発火タイミング |
|---|---|
head.meta | <head> 内、CSS の後 — メタタグ、確認タグなどを追加する。 |
footer.scripts | </body> の前、JS の後 — アナリティクスやウィジェットを追加する。 |
routes.registered | すべてのコアルートが登録された後、ページのキャッチオールの前。 |
router.before_dispatch | マッチしたハンドラーが実行される直前。引数:解決済みパス。 |
フィルター
| フック | 変更対象(引数) |
|---|---|
theme.template_data | テンプレートがレンダリングされる前のデータ配列。引数:($data, $templateName)。 |
head.css | 結合された CSS 出力文字列。 |
footer.scripts | 結合された JS 出力文字列。 |
video.card.html | ビデオカード全体の HTML。引数:($html, $video)。空でない文字列を返すと置き換えられる。 |
プラグインの構造
プラグインは plugins/ 配下のフォルダーで、マニフェストと PluginInterface を実装するクラスで構成されます。
plugins/myplugin/
├── plugin.json Manifest (name, slug, version, …)
├── myplugin.php Main class implementing PluginInterface
├── icon.svg Optional icon shown in the admin
└── … Your assets, templates, migrationsマニフェストはバンドルプラグインと同じ形式です:
{
"name": "My Plugin",
"slug": "myplugin",
"description": "What it does, in one sentence.",
"version": "1.0.0",
"author": "You",
"requires": "1.0.0",
"icon": "icon.svg"
}メインクラスは PluginInterface の 6 つのライフサイクルメソッドを実装します:
| メソッド | 呼び出しタイミング |
|---|---|
boot() | プラグインが有効な間、すべてのリクエストで呼び出される — ここでフック、ルート、アセットを登録する。 |
activate() | 管理者がプラグインを有効にしたとき。 |
deactivate() | 管理者が無効にしたとき。 |
install() | 初回有効化時 — テーブルを作成し、設定を初期化する。 |
uninstall() | プラグインが削除されたとき — クリーンアップを行う。 |
info() | マニフェストデータを配列で返す。 |
ルートとアセットの登録
すべての接続処理は boot() 内で行います:
public function boot(): void
{
// A front-end route
Router::get('/promo/{code}', [PromoController::class, 'show']);
// Inject a meta tag
HookSystem::addAction('head.meta', [$this, 'meta']);
// Tweak every video card
HookSystem::addFilter('video.card.html', [$this, 'badge'], 20);
}プラグイン内のスケジュールタスク
CronManager に定期タスクを boot() から登録します — 組み込みの疑似 cron で実行されるため、システムの crontab は不要です。これは CTR プラグインがスコアを再計算し、Backup Pro がスケジュールバックアップを実行する仕組みです。
参考としてのバンドルプラグイン
配布とライセンス
プラグインは非公開のまま保持したり、自由に共有したり、マーケットプレイス を通じて販売することができます。マーケットプレイスでは署名付きライセンスとドメインごとのアクティベーションが追加されます。プレゼンテーション側に関しては テーマ開発 を参照し、テンプレートコードで利用できるすべての機能については Theme API リファレンス を参照してください。