WordPress の管理画面の次の部分の表示内容を変更したいという要件がありました。
調べると、このデータには「views_{screen_id}」のフィルターフックでアクセスできます。ただここで問題なのは、{screen_id} の部分です。この部分は画面毎に動的に変化しますので、どこからか値を取得してきて、add_filter しないといけません。
さて、screen_id の取得と、それを使った同フィルターフックの登録は次のようにできます。
1 2 |
$screen = get_current_screen(); add_filter( 'views_' . $screen->id, 'my_hook_function_name' ); |
簡単ですね。
ただ実はここに問題がありまして、例えば「init」フックの中で get_current_screen() を実行しても、その値は null でスクリーンを得る事ができません。「wp_loaded」や「admin_init」フックの中でもダメでした。それならばと「pre_get_posts」の中でやってみると、無事スクリーンを取得できました。
では上記のコードを pre_get_posts フック内に書けば良いかというと、疑問が残ります。pre_get_posts フックは本来その目的のものではないからです。後日コードを見た時に、「なぜこんなところにこんなコードが入っているのだろう?」と、意味が分からなくなるかもしれません。コメントを付ければ良いですが、仕様以外のコメントは好きではありません(コメントが無くても意味が分かるコードを書くべき、という勝手な拘りです)。
そこで管理画面のアクションフックの一覧を眺めていて、良いフックを見つけました。
parse_request
ソースを確認すると、これはリクエストがパースされた直後に呼ばれるフックのようです。気付いてみると、リクエストがパースされなければ、その内容を WordPress が知る由もないわけで、当然このフック以前の「init」や「wp_loaded」で get_current_screen() が null を返すという挙動も理解できます。(誤りがあったようです。下記の追記で訂正しています)
結果、「parse_request」フックの中で「views_{screen_id}」のフィルターフックを登録することで、やりたいことが実現できました。
§ フック登録のタイミングについて
読み易さの観点から、フックの登録はなるべく1カ所にしたいと思っていますが、このように WordPress のアクティベーション ライフサイクルを気にしないといけない局面もあります。
そこで今回見つけた、「parse_request」アクションフックは、意味合い的にもなかなかグッドなフックの挿入タイミングでは無いかと思いました。僕がこれまで Web で検索したりした中では、あまりこのフックを使っている事例を見掛けなかったように思うのですが、どうでしょうか。フック登録のタイミングとして考えるとしたら、「init」をまず最初に挙げて、次に「parse_request」でも良いかな、と、今回思いました。新しく覚えたと同時に、ワリと重要なフックだという理解です。
実際のところはまだよく分からないので、これからその方針でやってみて、「違うな」と思ったら、パート2にでも書きたいと思います。
§ 追記 2013-03-21
その後色々と見回していると、また別のアクションフックを見つけました。
current_screen
このアクションフックは、WP_Screen を受け取ります。最初に例示した要件的には、そのものズバリですね! このフックは、Codex の管理画面のアクションフックの一覧には掲載されていませんでした(2013-03-21現在)。
で、面白いのは、このフックは次のタイミングで実行されていました。
…
deprecated_function_run
admin_init
current_screen
load-edit.php
parse_request
send_headers
parse_query
pre_get_posts
…
ということで、parse_request の過程(あるいは結果)でスクリーンが準備されるのだろうと予測した上の記述には間違いがありました。訂正します。とはいえ、parse_request は一つの良いタイミングだとは思います(でも呼ばれない時もあったりいたしますが…)。
ちなみに、開発者の為に、その画面のフック一覧が手軽に出せるような API は無いかなーと思いましたが、これは無かったです (^_^)。上記は、一時的に apply_filters や、do_action の中に Logger を配置して見つけました。