2026年8月21日
2026年8月21日
WordPressのadd_actionとadd_filterの使い方|書き方・コールバックの種類・すぐ使える実例
add_action() は「決まったタイミングで処理を実行させる」ための関数、add_filter() は「WordPressが扱う値を受け取って加工し、返す」ための関数です。どちらも「フック名・実行する関数・優先度・受け取る引数の数」の4つを渡すだけで使えます。この記事では、2つの関数の引数と戻り値、コールバックの書き方の違い、コードをどこに書くか、そして実際のサイト運用でよく使う書き方の実例と、つまずきやすい点を解説します。フックが内部でどう呼ばれるか、実行順や独自フックの作り方といった仕組みの話は扱わず、「今日 functions.php に書くコード」に絞った実践編です。
2つの関数の書式
add_action( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 );
add_filter( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 );
引数の並びはまったく同じです。実際、add_action() は内部で add_filter() を呼んでいるだけで、WordPressの中では両者は同じ仕組みで管理されています。それでも使い分けるのは、読む人に意図を伝えるためです。
- アクション(
do_action()で呼ばれるフック):戻り値は捨てられます。出力・保存・送信など「何かをする」処理を書きます。 - フィルター(
apply_filters()で呼ばれるフック):戻り値がそのまま次の処理に使われます。受け取った値を加工して、同じ型で返すのが約束です。
どちらの関数も戻り値は常に true なので、登録に成功したかどうかの判定には使えません。登録できているかは has_action() / has_filter() で確認します。
第3引数の優先度は小さいほど先に実行され、既定は10です。第4引数は「フックが渡す値のうち、いくつ受け取るか」で、既定の1のままだと最初の1つしか届きません。
コールバックの書き方は4通り
第2引数には「呼び出せるもの(callable)」なら何でも渡せます。後から外せるかどうかが違うので、用途で選びます。
<?php
// 1. 名前付き関数(外しやすく、最も分かりやすい)
function mytheme_add_body_class( $classes ) {
$classes[] = 'has-custom-header';
return $classes;
}
add_filter( 'body_class', 'mytheme_add_body_class' );
// 2. 無名関数(短く書けるが、外から remove_filter() できない)
add_filter( 'excerpt_more', function ( $more ) {
return '…';
} );
// 3. クラスの静的メソッド
class Mytheme_Setup {
public static function theme_supports() {
add_theme_support( 'title-tag' );
add_theme_support( 'post-thumbnails' );
}
}
add_action( 'after_setup_theme', array( 'Mytheme_Setup', 'theme_supports' ) );
// 4. インスタンスのメソッド(プラグインでよく使う形)
class Myplugin_Admin {
public function __construct() {
add_action( 'admin_notices', array( $this, 'notice' ) );
}
public function notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
echo '<div class="notice notice-info"><p>' . esc_html__( '設定を確認してください。', 'myplugin' ) . '</p></div>';
}
}
new Myplugin_Admin();
関数名には mytheme_ や myplugin_ のような接頭辞を付けます。add_body_class のような一般的な名前は、他のプラグインと衝突して「Cannot redeclare」の致命的エラーになることがあります。
無名関数は手軽ですが、親テーマや他の人が後から remove_filter() で外す手段がほぼありません。配布するテーマやプラグインでは名前付き関数かメソッドで登録しておくと、利用者が調整しやすくなります。PHP 8.1 以降の $this->method(...) という書き方(ファーストクラス callable)も無名関数として扱われるため、同じ注意が当てはまります。
コードをどこに書くか
フックを登録するコードの置き場所は、主に3つです。
- 子テーマの functions.php:見た目や表示に関わる調整。テーマを替えると効かなくなります。親テーマの functions.php に直接書くと、テーマの更新で消えます。
- **mu-plugin(
wp-content/mu-plugins/直下のPHPファイル)**:テーマを替えても残したい処理(XML-RPCの無効化、管理画面の制限など)。管理画面から停止できないぶん、誤って止められることがありません。サブフォルダ内のファイルは自動では読み込まれない点に注意します。 - 自作プラグイン:機能としてまとまっていて、有効化・停止を切り替えたい処理。
どこに書く場合も、本番で直接編集する前にバックアップを取り、ステージング環境で動作を確かめてから反映します。構文エラー1つで画面が真っ白になることがあるので、FTPやファイルマネージャーでファイルを戻せる状態にしておくと安心です。
よく使う実例
<head> にタグを出力する(アクション)
<?php
add_action( 'wp_head', function () {
echo '<meta name="theme-color" content="#1e73be">' . "\n";
}, 5 );
wp_head はテーマの header.php(ブロックテーマではコアが自動で出力)にある wp_head() の位置で実行されます。優先度を5にすると、多くのプラグインの出力より上に出ます。
簡単な機能のオン・オフ(フィルター+ヘルパー関数)
WordPressには __return_true・__return_false・__return_empty_array・__return_zero など、決まった値を返すだけの関数が用意されています。値を固定したいだけのフィルターなら、関数を自作する必要はありません。
<?php
// XML-RPC のメソッドを無効にする
add_filter( 'xmlrpc_enabled', '__return_false' );
複数の引数を受け取る(フィルター)
the_title はタイトルの文字列と投稿IDの2つを渡します。投稿IDを使うには第4引数を2にします。
<?php
add_filter( 'the_title', function ( $title, $post_id ) {
if ( is_admin() || ! in_the_loop() ) {
return $title;
}
if ( 'post' === get_post_type( $post_id ) && get_post_meta( $post_id, 'is_pr', true ) ) {
$title = '【PR】' . $title;
}
return $title;
}, 10, 2 );
the_title はメニューやウィジェット、管理画面でも呼ばれます。条件を付けずに文字を足すと、ナビゲーションの項目名まで変わってしまうため、上のように範囲を絞ります。
文字列の加工は型を守る(フィルター)
<?php
add_filter( 'document_title_separator', function ( $sep ) {
return '|';
} );
フィルターは、受け取ったのが文字列なら文字列、配列なら配列を返します。配列を受け取るフィルターで null や文字列を返すと、後続の処理で警告や致命的エラーが出ます。
つまずきやすい点
フィルターで値を返し忘れる
最も多い失敗です。return を忘れると値は null になり、タイトルや本文が消えたように見えます。条件分岐で早めに抜ける場合も、受け取った値をそのまま返してください。フィルターの中で echo するのも誤りで、出力が想定外の位置に出ます。
引数の数を指定していない
コールバックが2つ以上の引数を必須で受け取るのに第4引数を省くと、PHP 7.1 以降では ArgumentCountError で処理が止まります。WordPressが求めるPHPの最低バージョンは時期によって引き上げられるため、2026年10月現在の要件は公式サイトの動作環境のページで確認してください。フックが何を渡すかは、WordPress公式の開発者リファレンスでフック名を検索すると確認できます。
登録のタイミングが遅すぎる
フックは実行される前に登録しておく必要があります。たとえば init の中で add_action( 'plugins_loaded', ... ) と書いても、plugins_loaded はすでに終わっているので何も起きません。did_action( 'フック名' ) が1以上を返すなら、そのアクションは実行済みです。
同じフックの中で自分を呼び直してしまう
save_post の中で wp_update_post() を呼ぶと、保存のたびに save_post が再び実行されて無限ループになります。一時的に自分を外してから更新し、終わったら登録し直します。
<?php
function myplugin_sync_excerpt( $post_id, $post ) {
if ( wp_is_post_revision( $post_id ) || ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( '' !== $post->post_excerpt ) {
return;
}
remove_action( 'save_post', 'myplugin_sync_excerpt', 10 );
wp_update_post( array(
'ID' => $post_id,
'post_excerpt' => wp_trim_words( wp_strip_all_tags( $post->post_content ), 40 ),
) );
add_action( 'save_post', 'myplugin_sync_excerpt', 10, 2 );
}
add_action( 'save_post', 'myplugin_sync_excerpt', 10, 2 );
出力のエスケープを省く
フィルターを通った値は、他のプラグインによって何に変えられているかわかりません。HTMLに出すときは esc_html()・esc_attr()・esc_url() を出力の直前で使います。管理画面に関わる処理では current_user_can() で権限も確認します。
動作を確かめる方法
登録できたかは has_filter( 'body_class', 'mytheme_add_body_class' ) で確認でき、登録されていれば優先度の数値が返ります。ページ全体で実行されたフックと登録された関数を一覧したい場合は、Query Monitor プラグインが便利です(2026年10月現在)。パネルの名称や表示内容はバージョンで変わることがあります。調査はステージング環境で WP_DEBUG と WP_DEBUG_LOG を有効にして行い、wp-content/debug.log に警告が出ていないかもあわせて確認します。
まとめ
add_action()は処理の追加、add_filter()は値の加工。引数は同じで、内部の仕組みも共通- 第3引数で優先度(小さいほど先)、第4引数で受け取る引数の数を指定する
- コールバックは名前付き関数・静的メソッド・インスタンスメソッド・無名関数から選ぶ。外す可能性があるなら無名関数は避け、名前には接頭辞を付ける
- 置き場所は子テーマの functions.php、mu-plugin、自作プラグインから目的で選び、バックアップとステージングでの確認を先に行う
- フィルターは同じ型で値を返す。引数の数、登録のタイミング、
save_postの再帰、出力のエスケープに注意する