add_action()とadd_filter()の違いはサブルーチンとファンクションの違いのようなもの
add_action()
とadd_filter()
の違いを調べると「ほぼ同じ」という意見をよく見かけます。
似ているようででも違うその違いについては、
サブルーチン(手続)とファンクション(関数)という違いとして、
考えれば理解がしやすいのではないかと思います。
概要
ファンクション(関数)とサブルーチン(手続)の違い
サブルーチンという概念はPHPにはありませんが、
VBAなどでは返り値(戻り値)の有無で定義が分かれていたりします。
Subで定義しているものはサブルーチンで、
Functionで定義しているものはファンクションです。
123456789 Sub macro1()Dim str As Stringstr = func1()MsgBox str, vbInformationEnd SubFunction func1() As Stringfunc1 = "Hello VBA!"End Function(引用)【VBA入門】Functionの使い方(呼び出し、引数、戻り値) | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
その違いは、戻り値があるかないかの違いです。
ファンクションは「func1 = "Hello VBA!"
」として文字列を返しています。
では次に、WordPressのアクションとフィルターについて見てみます。
WordPressのアクションとフィルターの違い
WordPressのアクションとフィルターはカスタマイズをしたり、
プラグインの開発をしたりするときに使う機能で、
add_action(...)
やadd_filter(...)
を使って独自の処理を、
実行したいタイミングに実行させることができるようにする仕組みです。
WordPressでは「フックする」と呼び、
アクションフック、フィルターフックなどと言われますが、
「アクションとフィルターはほぼ同じです」とよく言われます。
というのも、サブルーチンとファンクションもほぼ同じで、
値を返してくる関数か、値を返さない関数かの違いなのですから、
ほぼ同じと言ってしまった方が楽なのだと思います。
私もVBAを習い始めた時先輩に、
この「値を返してくる関数か、値を返さない関数かの違い」だと教わって、
妙に納得した記憶があります。
では、アクションとフィルターの違いについて見てみましょう。
引用で申し訳ありませんが、手抜きですみません。
アクションとフィルターに関する処理は、「wordpress/wp-includes/plugin.php」に記述されています。アクションフックポイントを登録するためのメソッドとして、do_actionメソッドがあります。フィルターフックポイントを登録するためのメソッドとして、apply_filtersメソッドがあります。それぞれWordPressコアファイル内で次のように利用されています。
12345 // do_action使用例 「wordpress/wp-settings.php内の記述do_action( 'init' );// apply_filters使用例 「wordpress/wp-includes/formatting.php内の記述」$excerpt_length = apply_filters( 'excerpt_length', 55 );
次に、それぞれのメソッドの中身を見てみます。
1234567891011121314 // do_actionメソッド 抜粋 「wordpress/wp-includes/plugin.php内の記述」function do_action($tag, $arg = '') {(省略)call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));(省略)}// apply_filtersメソッド 抜粋 「wordpress/wp-includes/plugin.php内の記述」function apply_filters( $tag, $value ) {(省略)$value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));(省略)return $value;}アクションはコールバックの戻り値を利用してませんが、フィルターはコールバックの戻り値を利用していることがわかります。アクションとフィルターの違いをまとめると次のようになります。
- アクション フィルター 目的 特定のタイミングでユーザ独自の処理を実行させる。 特定のタイミングで特定の変数を変更させるためにユーザ独自の処理を実行させる。 コールバックの戻り値 なし あり フックポイントを登録するためのメソッド do_action()
do_action_ref_array()apply_filters()
apply_filters_ref_array()フックポイントの一覧確認 WordPress Codex(英語)
Plugin API/Action ReferenceWordPress Codex(日本語)
プラグイン API/アクションフック一覧WordPress Codex(英語)
Plugin API/Filter ReferenceWordPress Codex(日本語)
プラグイン API/フィルターフック一覧フックするためのメソッド add_action() add_filter() (引用)WordPress : アクションとフィルター | DN-Web64
メッセージ:そうか、コアファイルをちゃんと見れば良かったんだね。ありがとう!
どうでしょうか?
do_action()は戻り値がなく、(処理だけ実行したい)
apply_filters()は戻り値がある(何らかの出力がしたい)
PHPではファンクションとサブルーチンの違いの概念がないので、
定義上はすべてfunctionになります。
これを見れば、
戻り値のない do_action()はサブルーチン(Sub)。
戻り値がある apply_filters()はファンクション(Function)。
そう見ることができるのではないでしょうか。
ファンクションは値を受け取らなければサブルーチン実行
ファンクションは値を返す関数で、サブルーチンは値を返さない関数と考えると、
以下の様な場合、どうでしょうか。
1 2 3 4 5 6 7 8 9 |
function func1($p) { if($p%2==0) { return true; }else{ return false; } } func1(2); $ans = func1(4); |
5行目では、ファンクションを実行だけして値は受け取っていません。
6行目では、ファンクションを実行して、戻り値で値を受け取っています。
functionだからと言って、戻り値を使うか否かは、書き方次第です。
戻り値を返してくる(何らかの出力がある)
フィルターであっても戻り値を受け取っていなければ、
結果としてはアクションとして実行している事と同じというのが、
「ほぼ同じ」という表現になるのでしょう。
実際、この2つの関数の違いもパラメータ(引数)の違いはあるものの
最終的な処理は「call_user_func_array()」を呼び出しています。
do_action()
では、call_user_func_array()
を呼び出すだけ。
apply_filters()
では、$value = call_user_func_array()
として戻りを受け取り、return $value;
で返す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// do_actionメソッド 抜粋 「wordpress/wp-includes/plugin.php内の記述」 function do_action($tag, $arg = '') { (省略) call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); (省略) } // apply_filtersメソッド 抜粋 「wordpress/wp-includes/plugin.php内の記述」 function apply_filters( $tag, $value ) { (省略) $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); (省略) return $value; } |
やりたい事は、戻り値の有無といっていい事になります。
アクション定義されているものはフィルターとして呼び出せる
WordPressでこのadd_action()とadd_filter()で、
あれ?アクションだっけ、フィルターだっけ?となってしまう事がよくありますが、
内部的には「$wp_filter」というグローバル変数に関数が登録されます。
WordPress v4.9.6 – $wp_filterの配列キーと順を確認する為の環境です
厳密には違いがあるアクションとフィルターですが、
「アクションであってフィルター」と表現する方もおられる程に、
アクションで登録されているものは、フィルター($wp_filter)として登録されています。
厳密に違いを確認するには以下で確認できる表から、
「Type」の列を見れば「action/filter」と区分が分かります。
do_action()
で機能を実装しているか、
apply_filters()
で実装しているかの違いだけなのですけど。
WordPress 4.4 – List of all hooks and filters — Adam Brown, BYU Political Science
$wp_filterの中身を見れば、
どのような関数が登録されているのかは確認する事ができます。
(その時の処理に必要なものだけに限る)
極端なこと言えば、add_filter()
として呼び出すようにすれば、
フィルターに対しても、アクションに対しても有効な書き方になるという事になります。
段々「ほぼ同じ」という考えに近づいてきました。
「アクション(戻り値なし)」は「フィルター(戻り値あり)」に含まれる。
しかし、逆にフィルターとして登録されている関数(apply_filters()
)は、
「add_action()
」としてフックする事ができないんですね。
この点は注意が必要なわけで、あれ?動かない・・・という時、
フィルターに対して「add_action()
」をしているという事は稀に在ります。(自分)
以前の投稿でご紹介したものになりますが、以下では3つのフックを利用しています。
add_filter('query_vars', 'add_query_vars_filter' );
add_filter('generate_rewrite_rules', 'test_custom_endpoint' );
add_filter('init', 'test_flush_rewrite_rules');
すべて「add_filter()」で実装してしまっていますが、
先ほどのサイトで確認をすると以下のようになっています。
All plugin hooks in WordPress 4.4(中略)
- -Hook Type New? Instances 1177 query_vars filter no 1 570 generate_rewrite_rules action no 1 741 init action no 1 (抜粋引用)WordPress 4.4 – List of all hooks and filters — Adam Brown, BYU Political Science
2つはアクションになっています。(ソースを見ればいいんだろうけど)
という事は正しくは、以下のように書く必要があるという事になります。
add_filter('query_vars', 'add_query_vars_filter' );
add_action('generate_rewrite_rules', 'test_custom_endpoint' );
add_action('init', 'test_flush_rewrite_rules');
ただ、逆はだめなんですね。
フィルター定義されているものはアクションとしては呼び出せないわけじゃない(っておい!)
逆に、フィルターに対して「add_action()
」とした場合には?
add_action( 'query_vars', 'add_query_vars_filter' );
ここが「add_filter()
」なら動くのに、
「add_action()
」にしたら動かないという事になるはずでしたが動いてしまうとか鬱。
以下でも問題ないようなので、結構ファジーな感じですね。
add_action('query_vars', 'add_query_vars_filter' );
add_action('generate_rewrite_rules', 'test_custom_endpoint' );
add_action('init', 'test_flush_rewrite_rules');
まぁ、別に何かを出力している訳ではないので、
困らない。だから動くって事なのでしょう。
これが文字列表示とかをする必要があって、
戻り値を使うなら「add_action()
」ではうまく実現できないって事でしょうね。
面倒くさければ「add_filter()
で呼び出しとけ!」ってな、
乱暴なアプローチでもいいような、全部アクションとして呼び出してもいいような・・・。
毎回「WordPress 4.4 – List of all hooks and filters — Adam Brown, BYU Political Science」で
チェックしてから書くようにはしたいものですが。
ならやっぱり「ほぼ同じじゃん」って事に。
なんだこの結論。
当サイト内のコンテンツおよび画像を含むすべてにおいて、管理人アルゴリズンが著作権を保持しております。
当サイトでご紹介しております写真等につきましては著作権の放棄はしませんが、
ライセンスフリーでご利用いただいて構いません。
コンテンツを有益であると感じていただけましたら非常に光栄です。
ありがとうございます。
サイト内コンテンツを引用される際には、出典元として当サイト(個別記事)へのリンクをお願いいたします。
申し訳ございませんが、無断転載、複製をお断りさせて頂いております。
公開日: