2026年7月20日

2026年7月20日

WordPressのフックシステム(action/filter)の使い方|仕組み・実行順・独自フックの作り方

WordPressのフックは、コアやテーマ・プラグインの決まった地点に「ここで処理を差し込める」目印を置き、外から関数を登録できるようにする仕組みです。処理を追加するのがアクション、値を加工して返すのがフィルターで、どちらも内部では同じ仕組みで動いています。この記事では、フックが呼ばれる流れ、優先度と引数、主要なフックの実行順、登録した処理の外し方、自分のコードに独自フックを用意する方法、うまく効かないときの調べ方までを解説します。

フックの仕組み:置く側と登録する側

フックには「置く側」と「登録する側」があります。

  • 置く側:コアやテーマ、プラグインが do_action( 'フック名' ) や apply_filters( 'フック名', $値 ) を書いた地点
  • 登録する側:add_action( 'フック名', 関数 ) や add_filter( 'フック名', 関数 ) で、その地点で実行してほしい関数を登録するコード

WordPressは登録された関数をフック名ごとに保持しておき、do_action() や apply_filters() に処理が到達した時点で、登録順と優先度に従って呼び出します。つまり、add_action() を書いただけでは何も起きず、そのフックが実行される前に登録されている必要があります。これがフックを理解するうえで最も大切な点です。

アクションとフィルターの違い

アクション:処理を追加する

アクションは「この時点でこれを実行して」という指示です。戻り値は使われません。

<?php
// 記事の本文の後ではなく、ページ全体のフッターに出力する例
add_action( 'wp_footer', function () {
	echo '<p class="site-note">' . esc_html__( 'お問い合わせは平日10時〜17時に対応しています。', 'my-theme' ) . '</p>';
} );

フィルター:値を受け取って返す

フィルターは「この値を加工して返して」という指示です。受け取った値を返すことが前提で、返し忘れると値が空になります。

<?php
// 抜粋の文字数を変える
add_filter( 'excerpt_length', function ( $length ) {
	return 60;
} );

// 本文の末尾に文言を足す(個別ページのメインループだけに限定)
add_filter( 'the_content', function ( $content ) {
	if ( is_singular( 'post' ) && in_the_loop() && is_main_query() ) {
		$content .= '<p class="post-note">' . esc_html__( '記事の内容は公開時点の情報です。', 'my-theme' ) . '</p>';
	}
	return $content;
} );

フィルターの中で echo するのは誤りです。出力が想定外の位置に出たり、値が空になったりします。また the_content はウィジェットやRSS、抜粋の生成など本文以外の場面でも呼ばれるため、条件で範囲を絞っておくと副作用を防げます。

優先度と引数の数

add_action() と add_filter() は、第3引数に優先度、第4引数に受け取る引数の数を指定できます。

add_action( 'フック名', 'コールバック', 優先度(既定10), 引数の数(既定1) );
  • 優先度:数値が小さいほど先に実行されます。同じ優先度なら登録した順です。他のプラグインの処理より後に動かしたい場合は 20 や 99 のように大きくします。
  • 引数の数:フックが複数の値を渡していても、既定では最初の1つしか受け取れません。

たとえば save_post は投稿ID・投稿オブジェクト・更新かどうかの3つを渡すので、すべて使うには引数の数を3にします。

<?php
add_action( 'save_post', function ( $post_id, $post, $update ) {
	if ( wp_is_post_revision( $post_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ) {
		return;
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}
	// 保存時の処理
}, 10, 3 );

引数の数を指定せずに3つの引数を必須で受け取る関数を登録すると、PHP 7.1 以降では引数不足のエラー(ArgumentCountError)になります。フックが何を渡すかは、WordPress公式の開発者リファレンスで確認できます。

フック名には save_post_{$post_type} のように一部が変わる「動的フック」もあります。save_post_product と書けば、投稿タイプ product の保存時だけ実行されるので、関数の中で投稿タイプを判定する手間が省けます。

主要なフックの実行順

どのフックに登録すればよいかは、「その時点で何が使えるか」で決まります。フロントエンドを表示するときの主な流れは次のとおりです。

  1. muplugins_loaded:mu-plugin の読み込み完了
  2. plugins_loaded:通常のプラグインの読み込み完了
  3. after_setup_theme:テーマの functions.php の読み込み後。add_theme_support() はここで
  4. init:ユーザー情報が確定した後。カスタム投稿タイプやタクソノミーの登録はここで
  5. wp_loaded:WordPressの読み込みがひととおり完了
  6. template_redirect:表示するページが決まった後。リダイレクトやアクセス制御に向く
  7. wp_enqueue_scripts:CSS/JSの読み込み登録
  8. wp_head / wp_footer:テーマの wp_head() / wp_footer() の位置での出力

よくある失敗は、早すぎるタイミングで情報を使うことです。たとえば plugins_loaded の時点では is_single() などの条件分岐タグはまだ正しい結果を返しません。ページの種類で分岐するなら template_redirect 以降、ログインユーザーの権限を見るなら init 以降に登録します。

登録した処理を外す:remove_action / remove_filter

親テーマやプラグインが登録した処理を止めるには、remove_action() / remove_filter() を使います。外すときは、登録時と同じフック名・同じコールバック・同じ優先度を指定する必要があります。

<?php
// 親テーマの functions.php が優先度5で登録した処理を、子テーマから外す例
add_action( 'after_setup_theme', function () {
	remove_action( 'wp_head', 'parent_theme_custom_meta', 5 );
}, 20 );

ここでも順番が問題になります。子テーマの functions.php は親テーマより先に読み込まれるため、子テーマの直下で remove_action() を書いても、まだ親テーマが登録していないので何も外れません。上の例のように、親テーマが登録した後に実行されるフック(ここでは優先度を下げた after_setup_theme)の中で外します。

クラスのメソッドとして登録されている場合は、そのインスタンスを指定しないと外せません。プラグインがインスタンスを取得する関数やグローバル変数を用意していないか、ソースを確認してください。無名関数で登録された処理は、外から指定する手段がほぼありません。自分が書くコードでは、外せるように名前付き関数かクラスのメソッドで登録しておくと、後から調整しやすくなります。

自分のコードに独自フックを用意する

自作のテーマやプラグインに do_action() と apply_filters() を置いておくと、本体を直接編集せずに外から動作を変えられるようになります。

<?php
// 自作プラグイン側:フックを置く
function myplugin_render_cta() {
	$text = apply_filters( 'myplugin_cta_text', __( '資料をダウンロード', 'myplugin' ) );

	do_action( 'myplugin_before_cta' );
	echo '<a class="cta" href="' . esc_url( home_url( '/download/' ) ) . '">' . esc_html( $text ) . '</a>';
	do_action( 'myplugin_after_cta' );
}

// 利用する側(子テーマなど):値を差し替える
add_filter( 'myplugin_cta_text', function ( $text ) {
	return '無料で資料を受け取る';
} );

独自フックの名前には、プラグインやテーマ固有の接頭辞(例:myplugin_)を付けて、他のコードとの名前の衝突を避けます。また、フィルターを通した値は外部から何に変えられるかわからないので、上の例のように出力の直前でエスケープします。

フックが効かないときの調べ方

まず、どこまで処理が届いているかを確認します。調査はステージング環境で WP_DEBUG と WP_DEBUG_LOG を有効にして行うと安全です。

  • has_action( 'フック名', 'コールバック' ) / has_filter():登録されているか(登録されていれば優先度を返す)
  • did_action( 'フック名' ):そのアクションが何回実行されたか。0なら、登録した時点ではまだ実行されていない、またはそのページでは実行されないフック
  • current_filter():いま実行中のフック名
  • Query Monitor プラグイン:ページごとに実行されたフックと登録された関数を一覧で確認できます(パネルの名称はバージョンで変わることがあります。2026年10月現在)

効かない原因は、多い順に「フック名の綴り違い」「登録が実行より後になっている」「他の処理が後から上書きしている(優先度を上げて確認)」「フィルターで値を返していない」「条件分岐が早すぎるタイミングで使われている」です。functions.php を編集するときは、構文エラーで画面が真っ白になったときに元に戻せるよう、FTPやファイルマネージャーで接続できる状態にしておいてください。

まとめ

  • フックは「置く側(do_action / apply_filters)」と「登録する側(add_action / add_filter)」で成り立ち、登録はフックの実行より前に済ませる
  • アクションは処理の追加、フィルターは値を受け取って返す。フィルター内で echo せず、値を返し忘れない
  • 第3引数の優先度で実行順、第4引数で受け取る引数の数を指定する
  • after_setup_theme・init・template_redirect・wp_enqueue_scripts など、使いたい情報がそろうタイミングのフックを選ぶ
  • remove_action() は同じフック名・コールバック・優先度で、相手が登録した後に実行する
  • 独自フックには接頭辞を付け、has_action()・did_action()・Query Monitor で動作を確認する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲