mcpField
D
drupal-hooks

drupal-hooks

github.com/edutrul開発7351 回インストール21 週間前に更新
リポジトリ

drupal-hooks について

Drupal モジュール開発者向けの Drupal 11 Hook リファレンスです。`src/Hook/` のテスト可能なオブジェクト指向 Hook を優先し、手続き型 Hook やイベントサブスクライバーの使い分けも説明します。

主な機能

  1. 01属性を使ったオブジェクト指向 Hook の定義
  2. 02コンストラクターによる依存性注入
  3. 03Drupal 11.1+ の自動登録
  4. 04`src/Hook/` 外の Hook の手動登録
  5. 05Hook とイベントサブスクライバーの比較

活用シーン

  1. 01Drupal モジュールの新しい Hook の実装
  2. 02手続き型 Hook のクラスへのリファクタリング
  3. 03Hook とイベントサブスクライバーの選択

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/edutrul/drupal-ai --skill drupal-hooks

インストール後、Claude Code で/drupal-hooksを入力して読み込まれたか確認します。

同梱ファイルREADME.md

詳細

Drupal Hooks(Drupal 11)

OOP フック(推奨)

場所src/Hook/MyModuleHooks.php
名前空間Drupal\my_module\Hook
自動登録Drupal 11.1+(services.yml は不要)
DI サポートコンストラクターインジェクション
テスト可能はい — 直接インスタンス化し、モックを注入できます

例(ベストプラクティス)

<?php

namespace Drupal\my_module\Hook;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;

final class MyModuleHooks {

  use StringTranslationTrait; // Provides $this->t().

  public function __construct(
    private readonly AccountProxyInterface $currentUser,
  ) {}

  /**
   * Implements hook_form_node_article_form_alter().
   *
   * Prefer targeted form hooks over generic form_alter — they only fire for
   * the specific form ID and avoid unnecessary processing.
   */
  #[Hook('form_node_article_form_alter')]
  public function formNodeArticleFormAlter(array &$form, FormStateInterface $form_state): void {
    $form['title']['#title'] = $this->t('Article title');
  }

  /**
   * Implements hook_form_alter().
   *
   * Use only when acting on multiple forms or the form ID is unknown at
   * development time. Check $form_id explicitly.
   */
  #[Hook('form_alter')]
  public function formAlter(array &$form, FormStateInterface $form_state, string $form_id): void {
    if ($form_id === 'node_page_form') {
      $form['title']['#description'] = $this->t('Enter a descriptive page title.');
    }
  }

  #[Hook('node_presave')]
  public function nodePresave(NodeInterface $node): void {
    if ($node->getType() === 'article') {
      // Example: stamp the current user's ID on save.
      $node->set('uid', $this->currentUser->id());
    }
  }

  #[Hook('theme')]
  public function theme(): array {
    return [
      'my_template' => [
        'variables' => ['content' => NULL],
      ],
    ];
  }

}

注記: フックが実行されない場合は、名前空間と場所を確認してください。src/Hook/ の外にある OOP フックは、手動でサービス登録する必要があります。

services.yml

シナリオ必要ですか?
src/Hook/ にあり、名前空間が Drupal\my_module\Hook のクラスいいえ — 自動登録されます(Drupal 11.1+)
src/Hook/ の外にあるクラス(カスタムサービスなど)はい — 手動で登録してください

登録が必要な場合 — オートワイヤリングにより、型ヒントに基づいてコンストラクターの依存関係が解決されます:

namespace Drupal\my_module\Service;

use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Session\AccountProxyInterface;

final class MyCustomService {

  public function __construct(
    private readonly AccountProxyInterface $currentUser,
  ) {}

  #[Hook('form_alter')]
  public function formAlter(...): void {
    // ...
  }

}
services:
  Drupal\my_module\Service\MyCustomService:
    autowire: true

プロシージャルフック(.module)

my_module_hook_name() の命名規則により自動検出されます。現在も有効ですが、新しいコードでは OOP フックを推奨します。

フックとイベントサブスクライバー

フックを使用する場合イベントサブスクライバーを使用する場合
form_alter、エンティティフック、テーマフックディスパッチされた Symfony イベントへの反応
Drupal コア/コントリビュートの動作を拡張するPSR-14/疎結合システム
既存の Drupal API を使用する疎結合なロジックを構築する

src/Hook/ の OOP フックは完全にテスト可能です — クラスを直接インスタンス化し、モック化した依存関係を注入してください。

ルール(重要)

  • 新しい実装では、必ず src/Hook/ の OOP フックを優先してください
  • 明示的に依頼されない限り、.module に新しいフックを追加しないでください
  • プロシージャルフックが存在する場合は、OOP へのリファクタリングを提案してください

コメント