改めて学ぶ、アクションフックとフィルターフック。WordPressカスタマイズのポイントを抑えよう!

資料

動画

詳細

WordPressのカスタマイズで必須とも言える、アクションフックとフィルターフックの基本的な仕組みや、利用方法を学びます。これらを利用することで、直接テーマやプラグインを編集すること無く、カスタマイズが行えます。これらの仕組みを一緒に学びましょう!

■ こんな方にオススメ

  • コードを書いてWordPresssのカスタマイズを行っている人
  • フックの活用方法を改めて学び直したい人
  • wp_enqueue_scriptsをなんとなく利用している人

■ 講座内容

  • フックとは?
  • アクションフックとは?
  • フィルターフックとは?
  • 関連のタグ
  • PHPでの関数利用
  • アクションフックの利用
  • フィルターフックの利用

対象:WordPress ユーザー

日時:2024年7月24日(水) 日本時間 午後 21 時

参加方法:参加登録後、Zoom リンクが表示されます

最初にQA


フックとは?

そもそもなぜフックがあるのか?

  • WordPressを利用する場合に、コア、テーマ、プラグインなど、すべてを自作するわけでなく、今後もアップデートされる機能を使います。
  • それらを改変したい場合に、直接改変すると、次回のアップデート時にその変更は消えてしまいます。
  • そこで、フックの出番です。
  • フックを利用することで、フックが定義済の箇所であれば、直接コードを改変することなく、カスタマイズが可能です。

フックを使わない場合

  1. 実装したい内容を決定する
  2. 改変したい場所を見つける
  3. 該当箇所を直接変更する
  4. その時は良いが
  5. アップデート時にもとに戻る

フックを使う場合

  1. 実装したい内容を決定する
  2. 改変したい場所を見つける
  3. フックを利用して外部から変更を加える
  4. その時も良い
  5. アップデートしたとしても、元のファイルにフックの定義が残っていれば、変更が継続される

フックはつけたり外したり、同じところに複数つけて順番を並び替えたりできる

  • WordPressのコアでもフックを利用することで、あとから取り外したり、付け替えたりすることが簡単にできるように設計されています。
  • 以下のように、一つのフックに対して、複数の関数がフックされています。

wp-includes/default-filters.phpより

wp_headの場合(アクションフック)

wp_contentの場合(フィルターフック)

フックの記述方法

フックにはアクションフックとフィルターフックがあります(違いは後述)が、基本的に利用する場合の引数の書き方は同じです。

add_action( $hook_name, $callback, $priority, $accepted_args )

add_filter( $hook_name,  $callback, $priority, $accepted_args )

  • $hook_name : 利用したい定義場所名 | 省略不可
  • $callback : 実行したい関数名 | 省略不可
  • $priority : 優先順序 数が少ないほど先に読まれる | 省略可能 初期設定は10
  • $accepted_args : 許容される引数の数 | 省略可能 初期設定は1

add_action( ‘wp_head’, ‘wp_generator’ ); の場合は

wp_headのタイミングで、10番目(初期設定の優先度)でwp_generator関数を実行する。となります。

もしDocumentの見方がわかりにくい場合

  • the_title 辺りから始めると良いと思います
  • 関数について、引数の説明、なにが返ってくるか、実装されているソースの箇所と内容、関連のタグ、使い方のサンプル等が掲載されていてとても便利です。
  • ブラウザで日本語訳にしながら使うとだんだんなれてくると思います。

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

アクションフック

  • アクションは受け取った情報を受け取り、それを使って何かを実行し、何も返しません。言い換えると、アクションは何かに対して動作し、その後終了し、呼び出しフックに何も返しません。
  • アクションはコード フローを中断して何かを実行し、その後何も変更せずに通常のフローに戻ります。

フィルターフック

  • フィルターは受け取った情報を取得し、何らかの方法で変更して返します。言い換えると、何かをフィルタリングし、さらに使用できるようにフックに返します。
  • フィルターは、何かを特定の方法で変更し、その変更が後でコードで使用されるようにするために使用されます。

wp_head(アクションフック)の場合

  • wp_head自体は、ただの実行タイミングであり、そのタイミングで関数を実行させるために、フックが利用されています。
  • たとえばwp_generator関数では、WordPressのバージョン情報をmetaタグとして出力する。ということをwp_headのタイミングで実行します。

do_action( ‘wp_head’ ); => add_action( ‘wp_head’, ‘独自関数’ );

アクションフックの定義にはdo_actionが利用される

wp-includes/general-template.phpをみてみると、クラシックテーマを作成する際に必須となるwp_headとwp_footerの関数の記述があります。中身を見るとそれぞれ、do_actionとして、アクションフックの定義のみしかされていないことがわかります。

the_content(フィルターフック)の場合

  • the_contentの中身には本文があります。この本文を情報として受け取り、その本文対して何かしらの影響をくわえてから、戻すということをそれぞれの関数が行っています。
  • たとえば、do_shortcode関数では、本文を受け取って、その中にショートコードをルールに基づいた表記があった場合に、該当する関数を実行し、その結果を含めて本文を戻す。ということを実行しています。

フィルターフックの定義にはapply_filtersが利用される

wp-includes/post-template.phpを見てみると、本文を出力するthe_contentの関数の記述において、本文を表示する前に、apply_filtersが設定されているのがわかります。

apply_filters( ‘the_content’, $content ); => add_filter( ‘the_content’, ‘独自関数’ );

フックの利用方法

では実際にフックをどのように使うかを見てみましょう

アクションフックを利用し、wp_footerのタイミングで、隠しコメントとして`<!– 見つけた人は素敵 –>` を入れる

  1. 改変したい場所を見つける

wp_footerに do_action( ‘wp_footer’ ); があることを確認

  1. 隠しコメントを出力する関数を作成

任意の名前で関数を作成し、そのなかでecho関数を利用してメッセージを表示する用に設定

  1. フックの設定を実施

add_action関数を利用し、wp_footerのタイミングで my_hidden_message関数を実行します。その際に優先度を9999にすることで最後の方に実行することを期待します。

フィルターフックを利用し、コアが出力するタイトルタグのセパレータを – から|に変える場合

  1. 改変したい場所を見つける

wp-includes/general-template.php の中において、 wp_get_document_title() という関数で定義されています。前述のdo_actionと異なり、必ず2つ目のパラメーターに、必ずフィルターする対象があります。今回の場合は –

  1. フックを利用して外部から変更を加える

任意の名前で関数を作成し、そのなかで、フィルターする対象を受け取って、変更し返します

この際、第一引数にフィルターする対象を受け取れます。この変数名も任意に決定できます。

  1. フックの実施

add_filter関数を利用し、document_title_separatorのタイミングで my_document_title_separator関数を実行します。結果としてもともとは -だったものが| に変わって返されます。

関数名とフックの順序はどちらがいいか

フックを先に書いても

add_action( 'wp_head', 'hoge' );

function hoge() {

  echo 'hoge';

}

関数を先に書いても

function hoge() {

  echo 'hoge';

}

add_action( 'wp_head', 'hoge' );

どちらでも問題なく動きます。また、無名関数と呼ばれる、関数名を書かない記述方法もあります。

add_action( 'wp_head', function(){

  echo 'hoge';

});

無名関数にした場合は、簡単に書けるというメリットもある一方、あとからremoveや別のフック場所での再利用ができないなども、デメリットもあります。利用について考慮が必要でしょう。

私自身は関数についてインラインドキュメント(コード上に書く関数の説明)を書くので、関数を先に書くのが好きです。

<?php

/**

 * 隠しメッセージ

 */

function my_hidden_massage() {

    echo '<!-- 見つけた人は素敵 -->';

}

add_action( 'wp_footer', 'my_hidden_massag', 9999 );

PHPの関数をどこに書くか?

  • これまでにお伝えした通り、フックを利用するためには、独自関数を利用することが多いです。
  • この独自関数をどこに書くか? という問題について、多くの場合は「テーマのfunctions.phpに記述する。」と書かれているはずです。
  • ただ、こちらは、自作のプラグインとして記述することも可能です。
  • テーマを直接変更しないほうがいい場合(既存のテーマなどを利用している場合等)では、プラグインの利用のほうが良い場合もあります。
  • このあたりは、カスタマイズの量やカスタマイズの内容に応じて決めると良いと考えています。
  • 私の場合は、1からテーマを作るよりも、提供されているテーマをもとにして、サイトを作成することが多いので、プラグインとしてフックを利用することが多いです。

簡易的なプラグインの作り方

  • wp-content/pluginsのディレクトリの中に任意の名前のディレクトリをつくる hoge
  • そのなかにフォルダ名と同じ名前のphpファイルを作る hoge.php
  • 一番最初にPHPのコメントしてヘッダー部分を書く

<?php

/*

 * Plugin Name: YOUR PLUGIN NAME

 */

あらためて wp_enqueue_scriptsについて考えてみる

  • CSSなどを読み込む際に、「直接header.phpに書くのではなく、functions.phpから読み込むようにしましょう。」といった内容を目にすることがあるかと思います。
  • 実はこちらもアクションフックを利用した方法になっています。
  • あらためて、そのコードの例を見てみましょう

<?php

function my_enqueue_style() {

  wp_enqueue_style( 'my-theme', 'style.css', false );

}

add_action( 'wp_enqueue_scripts', 'my_enqueue_style' );

これまでに学んだことを考えると

add_action関数よってフックがされ、wp_enqueue_scripts のタイミングで _enqueue_style`が実行されているということがわかります。

そして my_enqueue_style関数の中では、wp_enqueue_styleという関数が利用されて、cssが設定されていそうです。

今回は、wp_enqueue_styleの説明は省きます。ポイントはアクションフックとして設定されているwp_enqueue_styleです。

より詳細の確認

これまでのwp_headやthe_contentなどは、テーマテンプレート内に記述があり、どのタイミング

実行されるかがわかりやすかったです。しかし、wp_enqueue_scriptsはテーマ内に記述がありません。これはどこにあるのでしょうか?

do_action( ‘wp_enqueue_scripts’ );を調べると

wp-includes/script-loader.phpの中に記述があります。

そしてこのwp_enqueue_scriptsという関数は

wp-includes/default-filters.phpにおいて、これもまたadd_actionとしてフックされています。

ということは、テンプレートから行くと

  • wp_head();が実行される
  • そのなかで do_action( ‘wp_head’ );が定義されている。
  • つまり、wp_headにフックのかかっているものが動く。
  • add_action( ‘wp_head’, ‘wp_enqueue_scripts’, 1 );というフックの設定記述がある
  • wp_enqueue_scripts()が実行される
  • そのなかでdo_action( ‘wp_enqueue_scripts’ );が定義されている
  • つまり、wp_enqueue_scriptsにフックのかかっているものが動く。
  • add_action( ‘wp_enqueue_scripts’, ‘my_enqueue_style’ );というフックの設定記述がある
  • my_enqueue_style();が実行される
  • その中には wp_enqueue_style( ‘my-theme’, ‘style.css’, false );が動く
  • wp_enqueue_styleは、wp_headにCSSの読み込みを追加する

という流れで、CSSが読み込まれます。とてもややこしいですね。こんなことなら、header.phpに直接書いたほうが直感的でわかりやすそうです。

なぜこうするのか?

  • テーマとプラグインなど複数のCSSやJSが読み込まれる可能性があります。
  • 自分だけで作成している場合は、headerに直接書いても良いかもしれませんが、他者の作った機能と合わせる際には、共通のルールでCSSやJSを読み込んだほうが、読み込み順序や、依存関係の解決、重複の回避などにも取り回しがよいです。
  • こういった理由で、フックを使って読み込むことが推奨されています。
  • 少なくとも、プラグインやテーマを開発し、公式ディレクトリにアップロードして公開する場合には、CSSやJSの読み込みについて、これらのフックの利用が必須のルールとして含まれています。

CSSやJS読み込みについての余談

  • wp_enqueue_scriptsを利用してCSSやJSを読み込む方法が主流ですが、このフックは表示画面側でしか、動きません。しかし、昨今はブロックエディター主流であり、CSSやJSについて表示画面と同じ、もしくは近いものが管理画面側にも読み込まれる必要性があります。
  • そこで、wp_enqueue_scripts以外にもCSSやJSを読み込むフックを利用します。
    • enqueue_block_assets
    • enqueue_block_editor_assets
  • この記事がとてもわかりやすいので、詳しくはこちらを呼んでください

アクションフックのタグ

ここまで、わかりやすさを重視して、テーマで利用されてるフックを紹介してきましたが、実はフックはそれだけではありません。WordPressでは、リクエスト実行時に動く様々なフックがあります。

表示までに通るフックとして以下のようなものがあります。

  • after_setup_theme
  • init
  • wp_loaded
  • pre_get_posts

これらを利用することで、WordPressのデフォルトの仕様に対してカスタマイズができます。

たとえば pre_get_posts フックを利用すると、メインクエリに対してカスタマイズができます。

<?php

/**

 * カテゴリーの記事一覧ではページあたりの表示件数を20件にする

 */

function change_posts_count_category_arcive($query) {

  if ( $query->is_category( '' ) ) {

    $query->set('posts_per_page', 20);

  }

}

add_action( 'pre_get_posts', 'change_posts_count_category_arcive' );

initフックを利用して投稿タイプを追加できます

<?php

/**

 * 投稿タイプの追加

 */

function my_cpt_init() {

  register_post_type(

    カスタム投稿タイプ追加の内容

   );

}

add_action( 'init', 'my_cpt_init' );

作業実行時に動くフックもあります

  • delete_user : ユーザー削除時
  • このフックを利用し、ユーザーが削除された場合に、メールを送ることも可能です。
  • ここではアクションフックですが、$user_idを受け取って活用しているところもポイントです

<?php

/**

 * ユーザーが削除されたタイミングで、該当のユーザーにメールを送る

 */

function my_delete_user( $user_id ) {

  global $wpdb;

  $user_obj = get_userdata( $user_id );

  $email = $user_obj->user_email;

  $headers = 'From: ' . get_bloginfo( "name" ) . ' <' . get_bloginfo( "admin_email" ) . '>' . "\r\n";

  wp_mail( $email, 'You are being deleted, brah', 'Your account at ' . get_bloginfo("name") . ' is being deleted right now.', $headers );

}

add_action( 'delete_user', 'my_delete_user' );

このようにフックを知れば知るほど、アイディア次第でWordPressはWebアプリケーションとしての可能性を発揮するはずです。

フィルターフックのタグ

フィルターフックについて書き換える他にも、追加するということもできます。

例えば、body_classに、表示している固定ページのスラッグを追加する場合

<?php

/**

 * 固定ページでは、body_classにページスラッグを page-slug という形で追加

 */

function add_slug_to_body_class( $classes ) {

  if ( is_page() ) {

    global $post;

    $classes[] = 'page-' . $post->post_name;

  }

  return $classes;

}

add_filter( 'body_class', 'add_slug_to_body_class' );

the_titleのフィルターを利用し、投稿の記事で、投稿日が閲覧した日より7日以内だった場合に、タイトルの後にnewをつける場合

引数を2つ関数内で扱うため、add_filterの第4引数も2になっています。

<?php

/**

 * 投稿の記事で、投稿日が閲覧した日より7日以内だった場合に、タイトルの後にnewをつける場合

 */

function add_new_to_recent_posts($title, $id) {

    // 現在の投稿タイプを取得

    $post_type = get_post_type($id);

    // 投稿タイプが 'post' でない場合は変更しない

    if ('post' !== $post_type) {

        return $title;

    }

    // 投稿の日付を取得

    $post_date = get_the_date('U', $id);

    $current_date = current_time('U');

    // 日付の差を計算

    $date_diff = $current_date - $post_date;

    // 過去7日以内かどうかをチェック

    if ($date_diff <= 7 * DAY_IN_SECONDS) {

        $title .= ' <span class="new-post">new!</span>';

    }

    return $title;

}

add_filter('the_title', 'add_new_to_recent_posts', 10, 2);

もともとの設定を書き換えるということもできます

excerpt_lengthを利用し、抜粋文の文字数を変更

<?php

/**

 * 抜粋の文字数を120文字に設定

 */

function custom_excerpt_length( $length ) {

     return 120;

}        

add_filter( 'excerpt_length', 'custom_excerpt_length', 20 );

フックを外す場合

以下のようにすると外れます。注意ポイントとしては、第三引数の数も揃える必要があります。

remove_filter( 'filter_name', 'function_name', 20 );

また、removeするタイミングも重要です。たとえば、 以下の4つのフィルターの場合、実行順序は以下のとおりですが

  1. after_setup_theme
  2. init
  3. wp_loaded
  4. pre_get_posts

3番のwp_loadedのタイミングで追加されているフックを、それよりも前のタイミングで外そうとしても外れません。この中でいうと、その後のpre_get_postsのタイミングで外す必要がありますので、以下のようにします。

<?php

/**

 * 任意のフィルターを外す

 */

function my_remove_filter(){

   remove_filter( 'filter_name', 'function_name', 20 );

}

add_action( 'pre_get_posts', 'my_remove_filter' );

まとめ

  • 初めての方は、なんとなくでも雰囲気を掴んでもらったら良いと思います。
  • そして、ドキュメントの例などから自分の必要なカスタマイズを実施していくと段々と慣れてくると思います。
  • これから何か、カスタマイズをしたいと思ったときに、まずは該当箇所にdo_actionやapply_filterがあるかどうかを調べるところから始められたら、それはきっととてもレベルアップです。
  • ぜひ、フックを使ってみてください。

著者情報