べんりワザ・WordPressのカスタマイズの土台

WordPressのフック入門(add_actionとadd_filter)

WordPressカスタマイズの土台になるフックの考え方。add_actionとadd_filterの違い、優先度と引数の指定、よく使うフック一覧、効かないときの原因をコード付きでまとめました。

WordPressのカスタマイズは、ほとんどがフックで成り立っています。フックとは「WordPressの処理の途中に、自分のコードを差しこむ場所」のこと。テーマのfunctions.phpに書くadd_action(...)add_filter(...)が、まさにそれです。

覚えることは2種類だけです。

  • アクション(add_action——そのタイミングで何かを実行する(戻り値は不要)
  • フィルター(add_filter——渡された値を加工して返すreturnが必須)

アクション:タイミングに処理を差しこむ

function my_enqueue_styles() {
  wp_enqueue_style('main', get_theme_file_uri('style.css'), [], '1.0');
}
add_action('wp_enqueue_scripts', 'my_enqueue_styles');

「CSSを読みこむタイミング(wp_enqueue_scripts)が来たら、この関数を実行して」という指定です。自分で呼び出す必要はなく、WordPressが適切なタイミングで呼んでくれます

フィルター:値を書きかえる

function my_excerpt_more($more) {
  return '…';        // ← 必ず返す
}
add_filter('excerpt_more', 'my_excerpt_more');

「抜粋の末尾の文字(excerpt_more)を作るとき、この関数に通してから使って」という指定です。受け取った値を加工してreturnするのが約束です。

書き方の型

add_action('フック名', '関数名', 優先度, 引数の数);
add_filter('フック名', '関数名', 優先度, 引数の数);
  • 優先度(既定10)——小さいほど先、大きいほど後に実行される
  • 引数の数(既定1)——2つ目以降の引数を受け取りたいときに指定する
// 抜粋の長さを、他の指定より後で確実に上書きする
add_filter('excerpt_length', fn() => 80, 999);

// 2つの引数を受け取る例
function my_title($title, $post_id) {
  return $post_id === 1 ? 'トップのお知らせ' : $title;
}
add_filter('the_title', 'my_title', 10, 2);

よく使うフック

フック名種類タイミング・用途
initaction初期化後。投稿タイプ・タクソノミー登録
after_setup_themeactionテーマ機能の有効化(add_theme_support
wp_enqueue_scriptsactionフロントのCSS・JS読みこみ
admin_enqueue_scriptsaction管理画面のCSS・JS読みこみ
wp_head / wp_footeractionheadの終わり・bodyの終わりに出力を足す
pre_get_postsactionメインクエリの条件を変える
save_postaction投稿の保存時に処理する
the_contentfilter本文の内容を書きかえる
the_titlefilterタイトルを書きかえる
excerpt_length / excerpt_morefilter抜粋の長さ・末尾
body_classfilterbodyのclassを足す
upload_mimesfilterアップロードできる拡張子を増やす
べんりワザCSSとJavaScriptの正しい読みこみ方(wp_enqueue)CSS・JSの読みこみ(wp_enqueue_scripts)の書き方はこちらべんりワザループの外で投稿を取得する方法(WP_Query)pre_get_postsでメインの一覧を調整する方法はこちら

実例1:本文の最後に共通の文章を足す

function my_after_content($content) {
  if (is_single() && is_main_query()) {
    $content .= '<p class="cta">最新情報はメールマガジンでお届けしています。</p>';
  }
  return $content;
}
add_filter('the_content', 'my_after_content');

is_single()などの条件で絞るのが大事です。条件を書かないと、一覧の抜粋や関係ないところにも足されてしまいます。

実例2:bodyにclassを足す

function my_body_class($classes) {
  if (is_front_page()) {
    $classes[] = 'is-front';
  }
  return $classes;
}
add_filter('body_class', 'my_body_class');

配列を受け取って配列を返すフィルターです。CSSで「トップだけ余白を変える」といった調整に使えます。

実例3:投稿を保存したときに処理する

function my_on_save($post_id, $post, $update) {
  if (wp_is_post_revision($post_id) || $post->post_type !== 'shohin') {
    return;
  }
  // 何か処理
}
add_action('save_post', 'my_on_save', 10, 3);

save_post自動保存やリビジョンでも走るので、最初にガードを入れるのが定石です。

無名関数で短く書く

PHPの無名関数(クロージャ)でも登録できます。短い処理では読みやすくなります。

add_action('after_setup_theme', function () {
  add_theme_support('post-thumbnails');
  add_theme_support('title-tag');
});

ただし無名関数はremove_action()で外せません(名前が無いため)。あとから解除する可能性がある処理は、名前付き関数にしておきます。

他のフックを外す

テーマやプラグインが登録した処理を止めたいときは、同じフック名・関数名・優先度を指定して外します。

add_action('init', function () {
  remove_action('wp_head', 'wp_generator');            // WordPressのバージョン表記を消す
  remove_filter('the_content', 'wpautop');             // 自動整形を止める(影響大なので慎重に)
});

優先度が違うと外せないので、登録側のコードを確認してから同じ値を指定します。

関数名の衝突を避ける

functions.phpはテーマ・子テーマの両方が読みこまれ、プラグインとも同じ名前空間を共有します。関数名には必ず接頭辞を付けます。

// ❌ ありがちな名前は衝突する
function setup() { … }

// ✅ サイト固有の接頭辞を付ける
function shimaenaga_setup() { … }
べんりワザ子テーマの作り方(最小構成)子テーマの作り方(functions.phpは上書きされない話)はこちら

まとめ

  1. フックは「WordPressの処理に自分のコードを差しこむ場所」。カスタマイズの土台
  2. action=タイミングで実行(return不要)/filter=値を加工して返す(return必須)
  3. 効かないときは優先度(第3引数)登録タイミングを疑う。引数を増やすなら第4引数
  4. 関数名には接頭辞を付ける。テーマを変えても残す処理はプラグインに置く

フックの考え方が入ると、「このプラグインの挙動を少し変えたい」といった要望にも手が届くようになります。

よくある質問

add_actionとadd_filterの違いは何ですか?
add_actionは「そのタイミングで処理を追加する」(戻り値は不要)、add_filterは「渡された値を加工して返す」(必ずreturnする)ものです。何かを出力・実行したいならaction、値を書きかえたいならfilterです。
フックはどこに書きますか?
テーマのfunctions.php、子テーマのfunctions.php、または自作プラグインです。テーマを変えても残したい処理は、テーマではなくプラグインに書きます。
add_filterで何も表示されなくなりました
フィルタ関数でreturnを書き忘れている可能性が高いです。filterは受け取った値を必ず返す約束なので、returnが無いと空になります。
フックが効きません
登録するタイミングがそのフックの実行より後になっていないか、優先度が他の処理に上書きされていないか、関数名のスペルが合っているかを確認します。優先度は第3引数で調整できます(大きいほど後に実行)。