WordPressのフィルターやアクションは何をしているのか

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

WORDPRESS Codex日本語版のプラグイン APIのフィルターとアクションの解説を要約すると、次のようになります。

フィルター

htmlデータとして出力されたり、データベースに登録されるデータを変更するために用意されたプログラムコード。
引数で値を受け取り、加工して返す。

アクション

特定のイベントで独自の処理をさせるために用意されたプログラムコード。

そして、フィルターとアクションを登録したり実行したりする仕組みがフックです。

フィルターとアクションは、WordPressにあらかじめ組み込まれています。
そして、非常に多くのフィルターとアクションが動作しています。
WordPressの本体はフィルターとアクションと言っていいくらいです。

プラグインやテーマの開発者は、新たにフィルターとアクションを登録したり、既存のものを無効化したりできます。

プログラム上での違い

フィルターとアクションは共に、特定のタイミングで実行されるプログラムです。
それぞれ、add_actionとadd_filterという関数で登録します。

  • // wp_head()で実行されるアクションを登録
  • add_action( 'wp_head', 'my_wp_head_func' );
  • // the_title()で実行されるフィルターを登録
  • add_filter( 'the_title', 'my_the_title_func' );
AFFS Simple Code Viewer
Copy

しかしwp-includes/plugin.phpで定義されているadd_action関数を見ると、おもしろいことがわかります。

  • function add_action( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
  • return add_filter( $hook_name, $callback, $priority, $accepted_args );
  • }
AFFS Simple Code Viewer
Copy

add_actionは、add_filterを呼び出しているだけでした。
つまりフィルターとアクションはプログラムコード上では、同じです。

しかしフィルターとアクションを実行は、少し異なります。

フィルターとアクションは特定のタイミングで呼び出されますが、内部ではフィルターはapply_filters関数が、アクションはdo_action関数が実行されます。

プログラム上での動作

フィルターのプログラム上での動作を追ってみます。

登録

add_filter関数はadd_action関数と同様に、wp-includes/plugin.phpで定義されています。

  • function add_filter( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
  • global $wp_filter;
  • if ( ! isset( $wp_filter[ $hook_name ] ) ) {
  • $wp_filter[ $hook_name ] = new WP_Hook();
  • }
  • $wp_filter[ $hook_name ]->add_filter( $hook_name, $callback, $priority, $accepted_args );
  • return true;
  • }
AFFS Simple Code Viewer
Copy

連想配列のキーとしてフック名を登録して、要素にWP_Hookのインスタンスをセットします。

一つのフックに対して、複数のコールバックを登録できます。
WP_Hookは、コールバック関数とプライオリティ(優先度)を管理しています。

アクションの実行

wp_head関数などアクションの起点となる関数の多くは、wp-includes/general-template.phpで定義されています。
この中で、wp_head関数は次のようになっています。

  • function wp_head() {
  • do_action( 'wp_head' );
  • }
AFFS Simple Code Viewer
Copy

wp_headはdo_actionを読んでいるだけですが、各々独自の処理をおこなって独自のタイミングでdo_actionを実行しています。
そのためアクションが実行される時点で、どのような状態になっているかはよく確認しておく必要があります。

do_action関数はwp-includes/plugin.phpで定義されています。
長いのでコードを掲載しませんが、ここではadd_filterで登録されている連想配列を確認して、コールバックを実行しています。

フィルターの実行

フィルターは特定の関数を実行したとき、戻り値を操作する方向で適用されます。

例えばget_the_title関数を実行すると、投稿記事のタイトルが取得され、そのタイトルに対してthe_titleフィルターが適用されます。
get_the_titleはwp-includes/post-template.phpで定義されています。

  • function get_the_title( $post = 0 ) {
  • $post = get_post( $post );
  • $title = isset( $post->post_title ) ? $post->post_title : '';
  • $id = isset( $post->ID ) ? $post->ID : 0;
  • if ( ! is_admin() ) {
  • if ( ! empty( $post->post_password ) ) {
  • $prepend = __( 'Protected: %s' );
  • $protected_title_format = apply_filters( 'protected_title_format', $prepend, $post );
  • $title = sprintf( $protected_title_format, $title );
  • } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
  • $prepend = __( 'Private: %s' );
  • $private_title_format = apply_filters( 'private_title_format', $prepend, $post );
  • $title = sprintf( $private_title_format, $title );
  • }
  • }
  • return apply_filters( 'the_title', $title, $id );
  • }
AFFS Simple Code Viewer
Copy

the_titleの他にprotected_title_formatやprivate_title_formatなどのフィルターが適用されていますね。
WordPressはフィルターやアクションが大量にあるのに資料が追い付いていないのが現状です。たぶん。
なのでソースコードを見た方が速いですね。

apply_filters関数はwp-includes/plugin.phpで定義されています。
do_action関数と同様に長いのでコードを掲載しませんが、ここではadd_filterで登録されている連想配列を確認して、コールバックを実行しています。

add_actionの中でadd_filterが呼ばれるような依存性は、do_action関数とapply_filters関数にはありませんが、アルゴリズム的にはほぼ同じです。