MENU

【WordPress×PHP】アクションフックの仕組みと使い方

【WordPress×PHP】オブジェクトとクラスの基本を解説
目次

はじめに

【WordPress×PHP】オブジェクトとクラスの基本を解説では、->と::の書き方を解説しました。

ここまでの実務サンプルでは、add_action( 'swell_before_post_head', function() { … } );のように、add_action()を何度も使ってきました。今回は、このadd_action()の仕組みであるアクションフックを解説します。優先度や引数の指定、SWELLの処理を外す方法まで押さえて、思った場所・思ったタイミングで処理を動かせるようになりましょう。

このシリーズの全15回の構成は、第1回の記事の冒頭にまとめています。

アクションフックとは?

WordPressやテーマのPHPファイルには、処理の途中のあちこちにdo_action( 'フック名' )という1行が書かれています。これがフック(差し込み口)です。

たとえば、ページの最後(</body>の手前)にはdo_action( 'wp_footer' )があります。add_action( 'wp_footer', 関数 )で関数を登録しておくと、WordPressがこの行まで来たときに、登録された関数をまとめて実行してくれます。

アクションフックの仕組み。ページを表示する流れの途中のdo_action('wp_footer')で、functions.phpのadd_actionで登録した関数が実行される
  • do_action():差し込み口を用意する側(WordPress本体・テーマ・プラグイン)
  • add_action():差し込み口に関数を登録する側(自分のfunctions.php)

テーマのファイルを直接書き換えなくても、決まったタイミングに処理を追加できるのがフックの便利なところです。なお、フックにはもう1種類、値を加工するための「フィルターフック」があり、次回解説します。

add_actionの書き方

add_action()には、4つの引数を指定できます。3つ目と4つ目は省略できます。

add_action( 'フック名', 実行する関数, 優先度, 受け取る引数の数 );
引数意味省略したとき
フック名どのタイミングで実行するか省略不可
実行する関数無名関数、または関数名の文字列省略不可
優先度同じフックの中で実行する順番10
受け取る引数の数フックから受け取る値の数1

実行する関数は、これまでの回のように無名関数で書く方法と、自作の関数を作って関数名を文字列で渡す方法があります。

// 無名関数で書く
add_action( 'wp_footer', function() {
	echo '<p>フッターに追加しました</p>';
} );

// 関数名を文字列で渡す
function kurumico_footer_text() {
	echo '<p>フッターに追加しました</p>';
}
add_action( 'wp_footer', 'kurumico_footer_text' );

どちらも動きは同じです。ただし、あとで紹介するremove_action()で外せるのは、関数名で登録したものだけです(無名関数は外せません)。

優先度:実行する順番を決める

同じフックに複数の関数を登録したときは、3つ目の引数の優先度で順番が決まります。ローカル環境で、wp_footerに優先度20・10・10・5の順で4つ登録して試しました。

add_action( 'wp_footer', function() { echo '<!-- 優先度20 -->'; }, 20 );
add_action( 'wp_footer', function() { echo '<!-- 優先度10 A -->'; } );
add_action( 'wp_footer', function() { echo '<!-- 優先度10 B -->'; } );
add_action( 'wp_footer', function() { echo '<!-- 優先度5 -->'; }, 5 );

ページのHTMLを確認すると、「優先度5 → 優先度10 A → 優先度10 B → 優先度20」の順に出力されていました。

優先度による実行の順番。functions.phpに優先度20、10のA、10のB、5の順で書いたところ、実際には5、10のA、10のB、20の順に実行された。その前にはSWELLの優先度1の処理が実行されている
  • 優先度の数字が小さいほど先に実行される
  • 同じ優先度なら、登録した順に実行される

SWELLも優先度を使い分けています。lib/output.phpの冒頭では、wp_headに優先度9と999で関数を登録していて、999の方には「カスタムCSSより後で出力する」というコメントが付いています。後から出力したいものほど、大きな数字を指定するわけです。

子テーマのfunctions.phpに最初から書かれているCSS読み込みのコードも、最後に11が指定されています。SWELLは自分のCSSを優先度8で読み込んでいるため、子テーマのstyle.cssはSWELLのCSSより後に読み込まれ、子テーマのCSSが優先されます。実際にHTMLを確認すると、child_style-cssはSWELLのmain.cssなどより後ろにありました。

引数を受け取る

フックによっては、do_action()で値を渡してくれるものがあります。たとえば、SWELLのsingle.phpには次の1行があります。

do_action( 'swell_before_post_head', $the_id );

表示中の記事の投稿IDを渡しているので、第5回の実務サンプルではfunction( $post_id )として受け取りました。

2つ以上の値を受け取るときは、4つ目の引数で受け取る数を指定します。値を2つ渡すフックで試しました。

// 4つ目を省略(1つだけ受け取る)
add_action( 'kurumico_test', function( $a, $b = 'なし' ) {
	echo "a={$a} b={$b}";
} );
do_action( 'kurumico_test', 'りんご', 'みかん' );  // a=りんご b=なし

// 4つ目に2を指定(2つ受け取る)
add_action( 'kurumico_test2', function( $a, $b = 'なし' ) {
	echo "a={$a} b={$b}";
}, 10, 2 );
do_action( 'kurumico_test2', 'りんご', 'みかん' );  // a=りんご b=みかん

4つ目を省略すると、do_action()が2つ渡していても、関数には1つ目しか届きませんでした。

WordPressのsave_post(記事を保存したとき)は、投稿ID・記事のオブジェクト(第8回のWP_Post)・更新かどうか、の3つを渡すフックです。3つとも使うなら、add_action( 'save_post', 関数, 10, 3 );のように4つ目に3を指定します。

主なアクションフックと実行される順番

投稿ページを開いたときに、主なアクションフックがどの順番で実行されるかを、ローカル環境で記録しました。

投稿ページを開いたときに実行されたアクションフックの順番。after_setup_themeからwp_footerまでを、準備・ページが決まる・HTMLの出力の3段階に分けて示している
フック名実行されるタイミング主な使い道
after_setup_themeテーマの読み込みが終わった親テーマの処理を外す
initWordPressの初期化投稿タイプ・ショートコードの登録
template_redirectテンプレートを選ぶ直前リダイレクト
wp_enqueue_scriptsCSS・JavaScriptの読み込みCSS・JSの追加
wp_head<head>の中metaタグの追加
wp_body_open<body>の直後計測タグの追加
wp_footer</body>の手前JavaScriptの追加

第7回で、条件分岐タグはwp以降のフックで使うと解説しました。この表でいえば、template_redirectから下のフックです。

SWELL独自のアクションフック

SWELLのテーマフォルダの中でdo_action(を検索すると、SWELL独自のアクションフックは次の4つでした(SWELL 2.19.0)。

フック名場所渡される値
swell_before_post_head記事タイトル部分の直前投稿ID
swell_before_post_thumb記事のアイキャッチ画像の直前投稿ID
swell_after_copyrightフッターの著作権表示の直後なし
swell_inner_main_visualトップページのメインビジュアルの中なし

ほかのテーマやプラグインでも、同じようにdo_action(で検索すると、使えるフックを探せます。VS Codeなら、フォルダを開いて「Ctrl + Shift + F」で検索できます。

フックを外す:remove_action

remove_action()を使うと、登録されている関数をフックから外せます。

remove_action( 'フック名', '関数名', 優先度 );

実は、SWELLの「SWELL設定」→「機能停止」タブも、この仕組みで動いています。たとえば「WordPressのバージョン情報を出力しない」にチェックを入れると、SWELLのlib/hooks/remove.phpで次のコードが実行されます。

remove_action( 'wp_head', 'wp_generator' );

wp_generatorは、<head>の中にWordPressのバージョンを出力するWordPress本体の関数です。これをwp_headから外しているわけです。

親テーマの処理を外すときの注意

子テーマから親テーマ(SWELL)の処理を外すときは、書く場所と優先度に注意が必要です。SWELLがwp_headに優先度9で登録している関数を外す実験で、書き方を変えて試しました。

書き方結果
functions.phpの一番外側に書く外れない
after_setup_themeの中で、優先度9を指定して書く外れる
after_setup_themeの中で、優先度を省略して書く外れない

第4回で解説したとおり、子テーマのfunctions.phpは親テーマより先に読み込まれます。一番外側に書くと、SWELLがまだ関数を登録していないので、外すものがありません。また、remove_action()は登録したときと同じ優先度を指定しないと外れません。

add_action( 'after_setup_theme', function() {
	remove_action( 'wp_head', '外したい関数名', 登録時の優先度 );
} );

SWELLのremove.phpでも、絵文字用のスクリプトを外すときはremove_action( 'wp_head', 'print_emoji_detection_script', 7 );と、WordPress本体が登録したときの優先度7を指定しています。

よくあるエラー

アクションフックで起きやすいエラーを、ローカル環境で確かめました(ファイルの場所は省略しています)。

関数名を間違えた(存在しない関数を登録した)

add_action( 'wp_footer', 'kurumico_footer_text' );  // この関数を作っていない

登録した時点ではエラーにならず、wp_footerが実行されたときに「重大なエラー」になりました。関数名のつづりと、関数を定義しているかを確認しましょう。

受け取る引数の数を指定し忘れた

add_action( 'save_post', function( $post_id, $post, $update ) {
	// …
} );  // 4つ目の「3」を書き忘れた

「1つしか渡されていないのに、3つ必要です」という意味です。4つ目の引数に3を指定します。

フック名を間違えた

add_action( 'wp_foter', … )のようにフック名を間違えても、エラーは出ませんでした。存在しないフックに登録しただけなので、何も実行されないまま終わります。エラーが出ないぶん気付きにくいので、「何も表示されない」ときは、まずフック名のつづりを確認しましょう。

実務サンプル:管理バーに「PageSpeed Insightsで計測」のリンクを追加する

ログイン中に記事を開いたとき、画面上部の管理バーから、その記事をPageSpeed Insights(Googleの表示速度の計測ツール)で計測できるリンクを追加してみましょう。

子テーマのfunctions.phpに、次のコードを追加します。

/**
 * 管理バーに「PageSpeed Insightsで計測」のリンクを追加する
 */
add_action( 'admin_bar_menu', function( $wp_admin_bar ) {
	if ( is_admin() || ! is_singular() ) {
		return;
	}

	$url = 'https://pagespeed.web.dev/analysis?url=' . rawurlencode( get_permalink() );

	$wp_admin_bar->add_node( [
		'id'    => 'kurumico-psi',
		'title' => 'PageSpeed Insightsで計測',
		'href'  => $url,
		'meta'  => [ 'target' => '_blank' ],
	] );
}, 100 );

ログインした状態で記事を開くと、管理バーの「SWELL設定」の右にリンクが表示されました。

SWELLの投稿ページの管理バー。「投稿を編集」「SWELL設定」の右に「PageSpeed Insightsで計測」のリンクが追加されている

コードのポイントは次のとおりです。

  • admin_bar_menuは、管理バーを組み立てるときに実行されるWordPressのフック。管理バーのオブジェクト(WP_Admin_Bar)を1つ渡してくれる
  • $wp_admin_bar->add_node()は、第8回で解説したオブジェクトのメソッド。配列で、項目のID・表示名・リンク先を指定している
  • 優先度に100を指定して、WordPressやSWELLの項目より後ろ(右側)に表示している
  • is_singular()(第7回)で、投稿ページと固定ページのときだけ表示している。is_admin()は管理画面かどうかを判定する関数
  • rawurlencode()で記事のURLを変換してから、PageSpeed InsightsのURLにつなげている

PageSpeed Insightsは、インターネットに公開されているページしか計測できません。ローカル環境ではリンクが表示されることだけ確認し、計測は本番サイトで試してください。

よくある質問・エラー対処

Q. 自分でフックを作ることはできますか?

→ できます。do_action( 'kurumico_after_notice' );のように、好きな名前で書けば、そこが新しいフックになります。名前がほかのテーマやプラグインと重ならないよう、自分用の接頭辞(この記事ではkurumico_)を付けましょう。

おわりに(まとめ)

まとめ

アクションフックを使えば、テーマのファイルを書き換えずに、決まったタイミングで処理を追加できます。

  • ✅ do_action()が差し込み口、add_action()がそこに関数を登録する
  • ✅ 優先度は小さい数字ほど先に実行され、省略すると10
  • ✅ 2つ以上の値を受け取るときは、4つ目の引数で数を指定する
  • ✅ SWELL独自のフックは、テーマフォルダを「do_action(」で検索すると見つかる
  • ✅ 親テーマの処理を外すときは、after_setup_themeの中で、登録時と同じ優先度を指定する
  • ✅ フック名を間違えてもエラーは出ないので、つづりに注意する

次回は、もう1つのフックである、フィルターフックについて解説します。

次回は、フィルターフック(add_filter)について解説予定です。

この記事が、少しでも誰かのお役に立てれば幸いです。

関連記事

当サイトの記事で使用したVBAなどのサンプルをDLできます

この記事のサンプルはありません!

ダウンロードページへは下のカードをクリックすればジャンプできます。
よろしければご利用ください!


【CSS】テキスト関連プロパティについて基本解説|Webの基礎


よかったらシェアしてね!
  • URLをコピーしました!
目次