WordPress のサブクエリにフックをかけるスタイリッシュな方法

前回のブログ記事 (Google Fonts はパラメータでサブセット化して Raleway の w を回避することもできるようです) が分かりづらいとメガネさんから不評でした、優太郎です。次の mgn-LENS ミーティングは明後日9日ですのでやはりブログを書きます。
今回は WordPress のサブクエリにいい感じでフィルターやアクションフックをかける方法を知りましたので紹介します。

例としてサブクエリの excerpt の長さと末尾のテキストを変更してみます。

クエリを作る

通常 WP_Query を使ってサブクエリを発行しますが、このクラスを継承した Custom_Query というクラスを作り、その内部メソッドにてフックの設定をします。メソッドは WordPress 側から参照されますので public でないと動きません。

[php]
class Custom_Query extends WP_Query {

function __construct( $args ) {

add_filter(‘excerpt_mblength’, array( $this, ‘custom_excerpt_length’ ));
add_filter(‘excerpt_more’, array( $this, ‘custom_excerpt_more’ ));

parent::__construct( $args );

remove_filter(‘excerpt_mblength’, array( $this, ‘custom_excerpt_length’ ));
remove_filter(‘excerpt_more’, array( $this, ‘custom_excerpt_more’ ));

}

/*
* Excerpt length
*/
public function custom_excerpt_length($length) {

return 10;

}

/*
* Excerpt suffix
*/
public function custom_excerpt_more($more) {

return ‘…’;

}

}
[/php]

あとは普通にこれを new すればよいです。

[php]
$args = array(
‘post_type’ => ‘post’,
‘posts_per_page’ => 99,
‘post_status’ => ‘publish’
);
$my_query = new Custom_Query( $args );
if( $my_query->have_posts() ):
while( $my_query->have_posts() ): $my_query->the_post();
the_excerpt();
endwhile;
wp_reset_postdata(); unset($my_query); endif;
[/php]

parent::__construct で親クラスのコンストラクタを呼び出します。

親クラスのコンストラクタで get_posts を実行していますので、これでフックが掛かった状態での結果が得られるという仕組みです。親クラスのコンストラクタを呼んだ後に念の為 remove_filter しておきます。

自分で $wp_query などのグローバル変数に値をセットして面倒な条件分岐からフックをかけるよりもスマートで手間も少なく、管理もし易いです。
この例だけだと有り難みは薄いですが、例えば

  • ajax でテキストフィールドの値からキーワード検索を取得し
  • ページ遷移無しで結果を得たい
  • かつ検索対象にカスタムフィールドも含めたい

といった感じのよくある ajax 検索が必要になった際など、重宝しています。