Umi Blog

ウミブログ

スタジオ・ウミが利用する Drupal hook ベスト 5

2026.09.18
南 千晶
スタジオ・ウミが利用する Drupal hook ベスト 5

こんにちは。 スタジオ・ウミの南です。

Drupalのhookは数が多く、どれから覚えるべきか迷いがちです。 そこで、当社が手がけたDrupalサイトのカスタムコードを調べ、よく使われているhookを数えました。 結果、上位3つはいずれも画面の出力に手を入れるhookでした。

Drupalでの構築経験があり、hookをひととおり知っている方に向けて、どのhookから押さえるとよいかの目安を紹介します。

調査の方法

ランキングの前に、どのサイトを対象に、何をどう数えたのかを説明します。 数字の受け取り方に関わるため、結果だけを知りたい方も目を通してみてください。

対象

  • 調査日:2026年9月18日
  • 対象:Drupal 9以降で、カスタムモジュールとカスタムテーマを持つ31サイト

数え方

  • 「使っているサイト数」を主とし、実装の総数を併記
  • 1つのサイトで同じhookを10回使っていても1サイト
  • サイト数が同じ場合は、実装数が多いほうを上位
  • 同じカスタムモジュールを持ち回っている兄弟サイト群は、まとめて1サイト(系列内で重複する実装も1件として数える)
  • hook_update_N・hook_install・hook_theme のように、必要になれば必ず書く定型のhookはランキングから除外

サイト数を主にしたのは、1つのプロジェクトで同じhookを多用しているだけの偏りを避けるためです。

抽出のしかた

hookの実装は、手続き型の関数とクラスベースのメソッドの両方を拾いました。 どちらか一方だけでは実態を見誤るためです。 具体的には、次の手順で抽出しています。

  1. 各サイトのリポジトリから、modules/custom・themes/custom・profiles/custom 配下のファイルだけを取得する
  2. 手続き型は、.module・.theme などのファイルから関数の定義を抜き出す。 関数名が「モジュールまたはテーマの機械名+_」で始まるものを候補にする。 機械名は、同じモジュールやテーマにある *.info.yml のファイル名から読み取る(mytheme.info.yml なら mytheme)
  3. クラスベースは、.php ファイルから #[Hook('...')] 属性を抜き出し、引数に書かれたhook名を候補にする
  4. 候補のhook名を、Drupalコア(11.4.6)の *.api.php に定義されている hook_〇〇 の一覧と照合し、一致したものだけを数える。 たとえば手続き型の mytheme_preprocess_node は、機械名を除いた preprocess_node を照合する。 クラスベースの #[Hook('preprocess_node')] は、引数の preprocess_node をそのまま照合する
  5. form_user_login_form_alter のようにフォームIDやテーマフック名が入るものは、hook_form_FORM_ID_alter などにまとめて数える(元の名前は内訳として残す)

4の照合により、コントリビュートモジュールが定義するhookや、フォームの送信処理のようにたまたま機械名で始まるだけの関数は数えていません。 そのため、この記事のランキングはコアが定義するhookに限ったものです。

Drupalのhookとは

hookは、Drupalが処理の要所で「何か変更や処理の追加をしたいモジュールはある?」と呼びかけ、各機能が「じゃあここ変更するね!」と割り込む仕組みです。 コアモジュールやコントリビュートモジュールなどの既存のコードを書き換えずに動作を変えられます。

長らく手続き型の関数で書くのが当たり前でしたが、Drupal 11系からは #[Hook] 属性を付けたクラスのメソッドとしても書けるようになりました。

手続き型のサポートは、早くてもDrupal 13で削除される見込みです(変更記録)。 今回の調査でも、クラスで書かれた実装が8サイト・54件ありました。 このうち7サイトはDrupal 11系です。 残る1サイトはDrupal 10系で、手続き型の関数からクラスのメソッドを呼びだす、Drupal 11系への移行を見越した書き方でした。 構築日の近いプロジェクトほど、この書き方に移っています。

集計前の予想

集計する前に、次のように予想していました。

  1. hook_preprocess_HOOK
  2. hook_form_FORM_ID_alter
  3. hook_theme_suggestions_HOOK

2位と3位はどちらが多いか見当がつきませんでしたが、1位は大差になるだろうと考えていました。 結果は最後に振り返ります。

第5位 hook_form_alter(12サイト/23実装)

サイト上のすべてのフォーム構築時に割り込むhookです。 フォームが組み立てられた直後に呼ばれ、項目の追加や削除、表示条件の変更ができます。 対象を絞らないぶん、条件分岐を自分で書く必要があります。

使われ方としては、複数のフォームに同じ調整をまとめて入れる場面が目立ちました。

  • 特定の権限を持つ利用者にだけ項目を隠す
  • 管理画面のフォーム全般に説明文を足す

1つのフォームだけが対象なら、hook_form_FORM_ID_alter のほうが適しています。

第4位 hook_page_attachments_alter(18サイト/33実装)

hook_page_attachments_alter は、ページに読み込まれるCSS・JavaScriptや head 内のメタ情報を、HTML出力の直前に変更・削除するためのhookです。 他モジュールが読み込んだ不要なアセットを取り除いたり、既存の設定を上書きする際に使用します。

18サイトで使われている一方、実装は33件と少なく、ほとんどのサイトでは1〜2か所でした(11か所あったのは、兄弟サイト群をまとめて1サイトとして数えたものです)。 用途は次のようなものです。

  • アクセス解析タグの読み込み
  • 特定の条件下だけでのライブラリ追加
  • 不要になったコアのライブラリの除去

いずれも多くのサイトに1つか2つある「全体に関わる決め事」で、それを書く場所として使われています。

第3位 hook_theme_suggestions_HOOK_alter(19サイト/97実装)

テンプレートの候補名を増やしたり並べ替えたりするhookです。 候補を増やすことで、node--news--teaser.html.twig のように条件を絞ったテンプレートファイルを使えるようになります。 Twig側の条件分岐(if文)を最小限に抑えられるのが最大のメリットです。

名前のよく似た hook_theme_suggestions_HOOK もあります。 こちらは自分のモジュールから候補を提案するものです。 一方、今回の3位である _alter が付くほうは、集まった候補の一覧を受け取って並べ替えたり削除したりできます。 他のモジュールやテーマが出した候補にも手を入れられるぶん、実務では _alter のほうがよく使われていました。

対象の内訳は次のとおりです。

  • フォーム:17件
  • ブロック:7件
  • メニュー:7件
  • フィールド:6件

フォームごとに異なるマークアップを当てたい、同じブロックでも配置場所によって見た目を変えたい、といった要望に応えるための使い方です。 デザインの都合をテンプレートの出し分けで解決する場面が多く見られました。

第2位 hook_form_FORM_ID_alter(23サイト/120実装)

フォームIDを指定して、そのフォームだけに手を入れるhookです。 第5位の hook_form_alter と役割は同じですが、対象が1つに絞られるぶん、条件分岐が不要になり、コードの可読性やメンテナンス性が高まります。 また、対象フォームの生成時のみ実行されるため効率的です。

対象の内訳は次のとおりです。

  • Viewsの絞り込みフォーム(views_exposed_form):20件
  • ノードの編集フォーム:15件
  • ログインフォーム:8件
  • ユーザー編集フォーム:8件

検索や一覧の絞り込みの表示を整える、編集画面の項目の並びを実務に合わせる、といった調整が中心でした。

なお、120件のうち11件はすでに #[Hook] 属性を使ったクラスとして書かれており、ベスト5のなかでは新しい書き方への移行が最も進んでいます。

第1位 hook_preprocess_HOOK(28サイト/392実装)

Twigテンプレートに渡す変数を、描画の直前に用意・加工するためのhookです。 テンプレート側のロジックを減らし、表示に必要な値をPHP側で整えられます。

31サイト中28サイトで使われ、実装数は392件と、2位の3倍を超えました。 予想どおり、大差での1位です。 対象の内訳は次のとおりです。

  • page:33件
  • html:31件
  • views_view:26件
  • node:25件
  • breadcrumb:21件

具体的には、次のような用途で使われていました。

  • パンくずの先頭に項目を足す
  • 一覧に表示する日付の書式を整える
  • 記事に紐づく別のコンテンツを変数として渡す

どれもテンプレートだけでは書きにくく、かといって独自のブロックやフィールドを作るほどではない、という隙間を埋めています。 この「隙間を埋められるちょうどよさ」が実装数の多さにつながっているのだと感じました。

まとめ

ベスト5は次のとおりでした。

順位hookサイト数実装数
1hook_preprocess_HOOK28 / 31392
2hook_form_FORM_ID_alter23 / 31120
3hook_theme_suggestions_HOOK_alter19 / 3197
4hook_page_attachments_alter18 / 3133
5hook_form_alter12 / 3123

上位3つは、テンプレートに渡す変数、フォームの中身、テンプレートの選び方と、いずれも画面の出力に手を入れるhookでした。 コンテンツの構造や項目はサイトビルディングで組み立て、最後の見え方の調整にhookを使う、という進め方が数字にも表れています。 逆に、エンティティの保存時に処理を挟む hook_ENTITY_TYPE_presave のようなhookは8サイトにとどまりました。

予想と照らすと、1位から3位まではほぼ的中でした。 「ほぼ」というのは、3位に挙げていたのが hook_theme_suggestions_HOOK で、実際に多かったのは _alter が付くほうだったためです。 1位が大差になるという見立ても、実装数で2位の3倍を超えたという形で当たっています。 一方で4位以下は予想できていませんでしたが、hook_page_attachments_alter が18サイトと上位に入ったのは意外でした。 ほとんどのサイトで1〜2か所しか書かないものが、これだけ多くのサイトで必要とされているということです。

hookをひととおり覚えようとすると数の多さに気圧されますが、実務で繰り返し登場するものは限られます。 まずは上位3つを押さえておくと、たいていの場面で足りるはずです。

なお、新しくhookを実装する際は、使っているDrupalのバージョンでの対応状況を確かめたうえで、#[Hook] 属性を使ったクラスでの実装も検討してみてください。

南 千晶

南 千晶

南 千晶エンジニア

スタジオ・ウミのフロントエンドエンジニア。ものづくりが好きで、広く浅くではなくスペシャリストとして専門性を高めたいという想いから2023年に参画しました。現在は HTML/CSS を使った実装を中心に担当しています。こよなく愛するものは家族、美容、甘いもの。モットーは「死ぬ時後悔しない選択を取ること」。

\

小さなご意見も、私たちにとっては大きなヒントです!

ぜひ率直なご感想をお寄せください

/

この記事はお役に立ちましたか?

スタジオ・ウミのメンバー

Masters of Drupal Engineering.

人に、技術に、品質に、まっすぐ。

Download
会社案内をダウンロード
Contact
お気軽にお問い合わせください
Recruit
スタジオ・ウミの採用情報