フィルターフック・アクションフック
WordPress にはフィルターフック・アクションフックと
呼ばれるプラグイン用の API が用意されています。
これらのフックは、WordPress が動作する様々なタイミングで、
プラグインから登録された関数があるか判断し、もしあれば
その関数を走らせることによって、WordPress のデフォルトの
動作を変更します。
例えば「the_content」
というフィルターフックに関数を登録すれば、記事本文を変更できます。
1 | function korosukenize( $content ) { |
2 | $content = preg_replace( |
8 | add_filter( 'the_content' , 'korosukenize' ); |
こんな感じのプラグインを書いてやるだけで、
記事本文の語尾をコロ助風に変換できます。
適切なフックを探すには?
では、自分のプラグインで使用したいフィルターフック・アクションフックを探すにはどうすれば良いでしょうか?
通常は、WordPress Codex のフィルターフック一覧、アクションフック一覧を参照します。
しかし Codex に詳しく載ってないような、マニアックな
フィルタフック・アクションフックを探したい時は、
どうすれば良いでしょうか?
私の場合は WordPress のソースから使えそうな
アクションフック・フィルタフックを探します。
ただし、WordPress のソースを頭から全部読んでたら
日が暮れるので、それらしいところのニオイを嗅ぎ分ける
鼻を養う必要があります。
その辺のノウハウを実際の例を交えて簡単に説明します。
WordPress ソースの探索
以下の2点に注意して、WordPress ソース内を探検していきます。
使用する武器は grep 辺りが適切でしょう。
- アクションフックが適用されるのは、関数 do_action() が実行された時
- フィルタフックが適用されるのは、関数 apply_filters() が実行された時
他の方法としては wp-includes/default-filters.php を眺めて見るのもアリです。
このファイルを眺めると、デフォルトで登録されているフィルタフックが確認できます。
似たようなことをしている既存の WordPress プラグインのソースを見ても良いでしょう。
その場合は add_filter(), add_action() を探してみてください。
では、使えるプラグインフックの探索方法を実例を交えて紹介します。
RSSフィードに独自のテンプレートを適用できるか?
RSSフィード用のテンプレートは、コアファイルにしか存在
しないため、通常の WordPress テーマでは、RSSフィードは
カスタマイズできません。
しかし、これを変更して右上にアイコンを表示したいとかの
要望が出てきたらどうすれば良いでしょうか?
これは、適切なプラグインフックを使用することで実現できます。
フィードのテンプレートとしては wp-includes/feed-rss.php が読み込まれています。
これは、使用しているテーマに関わらず固定です。
WordPress のソースを grep して feed-rss.php を読み込んでいるところを探索しましょう。
→ wp-includes/functions.php の do_feed_rss() で読み込んでますね。
1668 | function do_feed_rss() { |
1669 | load_template( ABSPATH . WPINC . '/feed-rss.php' ); |
続いて、この do_feed_rss() 関数を呼び出しているところを探索しましょう。
→ wp-includes/default-filters.php の中で
add_action('do_feed_rss', 'do_feed_rss', 10, 1); していますね。
193 | add_action( 'do_feed_rdf' , 'do_feed_rdf' , 10, 1 ); |
194 | add_action( 'do_feed_rss' , 'do_feed_rss' , 10, 1 ); |
195 | add_action( 'do_feed_rss2' , 'do_feed_rss2' , 10, 1 ); |
196 | add_action( 'do_feed_atom' , 'do_feed_atom' , 10, 1 ); |
197 | add_action( 'do_pings' , 'do_all_pings' , 10, 1 ); |
198 | add_action( 'do_robots' , 'do_robots' ); |
199 | add_action( 'sanitize_comment_cookies' , 'sanitize_comment_cookies' ); |
200 | add_action( 'admin_print_scripts' , 'print_head_scripts' , 20 ); |
201 | add_action( 'admin_print_footer_scripts' , 'print_footer_scripts' , 20 ); |
202 | add_action( 'admin_print_styles' , 'print_admin_styles' , 20 ); |
203 | add_action( 'init' , 'smilies_init' , 5 ); |
204 | add_action( 'plugins_loaded' , 'wp_maybe_load_widgets' , 0 ); |
205 | add_action( 'plugins_loaded' , 'wp_maybe_load_embeds' , 0 ); |
206 | add_action( 'shutdown' , 'wp_ob_end_flush_all' , 1 ); |
207 | add_action( 'pre_post_update' , 'wp_save_post_revision' ); |
208 | add_action( 'publish_post' , '_publish_post_hook' , 5, 1 ); |
209 | add_action( 'future_post' , '_future_post_hook' , 5, 2 ); |
210 | add_action( 'future_page' , '_future_post_hook' , 5, 2 ); |
211 | add_action( 'save_post' , '_save_post_hook' , 5, 2 ); |
212 | add_action( 'transition_post_status' , '_transition_post_status' , 5, 3 ); |
213 | add_action( 'comment_form' , 'wp_comment_form_unfiltered_html_nonce' ); |
214 | add_action( 'wp_scheduled_delete' , 'wp_scheduled_delete' ); |
このアクションフック do_feed_rss を実際に起動している
箇所を探索しましょう。
→ wp-includes/functions.php の do_feed() 内で
'do_feed_' . $feed を do_action() しています。
1637 | $feed = get_query_var( 'feed' ); |
1640 | $feed = preg_replace( '/^_+/' , '' , $feed ); |
1642 | if ( $feed == '' || $feed == 'feed' ) |
1643 | $feed = get_default_feed(); |
1645 | $hook = 'do_feed_' . $feed ; |
1646 | if ( !has_action( $hook ) ) { |
1647 | $message = sprintf( __( 'ERROR: %s is not a valid feed template' ), esc_html( $feed )); |
1651 | do_action( $hook , $wp_query ->is_comment_feed ); |
do_feed() 関数を実際に呼んでいるところを探索しましょう。
→ wp-includes/template-loader.php の中で is_feed() なら、
この関数を呼んでますね。
06 | if ( defined( 'WP_USE_THEMES' ) && constant( 'WP_USE_THEMES' ) ) { |
07 | do_action( 'template_redirect' ); |
09 | do_action( 'do_robots' ); |
11 | } else if ( is_feed() ) { |
14 | } else if ( is_trackback() ) { |
15 | include (ABSPATH . 'wp-trackback.php' ); |
17 | } else if ( is_404() && $template = get_404_template() ) { |
20 | } else if ( is_search() && $template = get_search_template() ) { |
23 | } else if ( is_tax() && $template = get_taxonomy_template()) { |
これで、RSS フィードがリクエストされた場合、
WordPress が以下の動作をすることがわかりました。
- フィードがリクエストされたら do_feed() 関数を呼び出す
- do_feed() 関数が 'do_feed_rss' アクションフックを呼び出す
- アクションフックとして登録された do_feed_rss() 関数が動作する
- ABSPATH . WPINC . '/feed-rss.php' をテンプレートとしてロードする
do_feed_rss() 関数の中では、テンプレートファイルは「ABSPATH . WPINC . '/feed-rss.php'」固定です。
しかし、この do_feed_rss() 関数はアクションフックとして登録されているため、このアクションフックをリムーブ後、独自のアクションフックを登録すれば、目的のことができそうですね。
というわけで、テーマフォルダ内にあるRSSフィード用テンプレート(feed-rss.php)を読み込むプラグインができました。
02 | remove_filter( 'do_feed_rss' , 'do_feed_rss' , 10); |
05 | function custom_feed_rss( $for_comments ) { |
06 | $template_file = '/feed-rss' . ( $for_comments ? '-comments' : '' ) . '.php' ; |
07 | $template_file = ( file_exists ( get_template_directory() . $template_file ) |
08 | ? get_template_directory() |
11 | load_template( $template_file ); |
13 | add_action( 'do_feed_rss' , 'custom_feed_rss' , 10); |
他のフィード ( rss2, atom ) についても、同様にしてやれば安心です。
WordCamp Yokohama 公式サイトのプロフィール登録画面のカスタマイズも、プラグインフックを登録するだけで実現しています。
公式サイトのプロフィール登録画面で使用しているプラグインフックは以下のとおりです。
- profile_personal_options
- show_user_profile
- edit_user_profile
- personal_options_update
- edit_user_profile_update
- user_contactmethods
- admin_print
- admin_head-profile.php
- admin_footer-users.php
- manage_users_columns
- manage_users_custom_column