WordPressの3.3で、新しい関数 is_main_query が使えるようになりました。
WordPress をカスタマイズをガッツリ行う方には、是非知っておいていただきたいものです。
といっても、有用なのは関数ではなく、クラスメソッドの方ではありますが。。
表示カスタマイズ方法のおさらい
例えば、カテゴリーアーカイブだったら表示する件数を5件にしたい時や、年月アーカイブでは特定のカテゴリーを除きたい時などどうしていますか?
簡単にやるのであれば query_posts を使い、その条件で記事を取得する方法ですが、これは、データベースへのアクセスが増えるので、パフォーマンス的にはあまりおすすめできません。速くするためにCSSスプライトを使ったりするのに、これではちょっと本末転倒な気もしますよね。
一番いいのは、WordPress が標準で表示する記事の条件を状況に応じて変更してあげて、デフォルトで表示するものそのものを変えてあげる方法です。方法は意外と簡単で pre_get_posts フックで、引数で渡されてくるオブジェクトを、ちょろっと変えてあげるだけで実現できたりします。
CODE 1 カテゴリーアーカイブだったら表示する件数を5件にする
function category_display_five_articles( $wp_query ) { if ( $wp_query->is_category() ) { $wp_query->set( 'posts_per_page', 5 ); } } add_action( 'pre_get_posts', 'category_display_five_articles' );
CODE 2 年月アーカイブでは未分類を表示しない
※ 404になる場合があるので注意!
function date_archive_exclude_uncategorize( $wp_query ) { if ( $wp_query->is_date() ) { $wp_query->set( 'cat', -1 ); } } add_action( 'pre_get_posts', 'date_archive_exclude_uncategorize' );
is_main_queryの使い方
で、ここで、ようやく本題に戻ってきます。WordPress では、標準で表示する記事の他に、関連記事や最新情報などの取得に query_posts や get_posts が使われたり、その他にもナビゲーションメニュー機能を利用している場合は、このメニューデータの取得にも get_posts が利用されています。
CODE 1、CODE 2のフックは、標準の記事取得以外の query_posts や get_posts にも効いてしまうため、状況によっては想定と違う結果が出てしまったりして、ドツボにはまりかねません。
そんなとき、WordPress の標準のクエリーか、テンプレートから呼び出されたのかを判別するのが、 is_main_query というわけです。
先のCODE 1、CODE 2を、is_main_query を用いて書き直すと、
CODE 3 カテゴリーアーカイブだったら表示する件数を5件にする
function category_display_five_articles( $wp_query ) { if ( $wp_query->is_main_query() && $wp_query->is_category() ) { $wp_query->set( 'posts_per_page', 5 ); } } add_action( 'pre_get_posts', 'category_display_five_articles' );
CODE 4 年月アーカイブでは未分類を表示しない
※ 404になる場合があるので注意!
function date_archive_exclude_uncategorize( $wp_query ) { if ( $wp_query->is_main_query() && $wp_query->is_date() ) { $wp_query->set( 'cat', -1 ); } } add_action( 'pre_get_posts', 'date_archive_exclude_uncategorize' );
となり、他に影響を与えなくなります。
3.2以下の場合
3.3未満の場合は、どうすりゃいいの?という話ですが、 is_main_query メソッドの中身は単純で、
function is_main_query() { global $wp_the_query; return $wp_the_query === $this; }
と、オブジェクトの同一比較を行っているだけだったりします。
つまり、ちょっとだけ記述が増えますが、is_main_query が使えないバージョンでは、
CODE 5 WordPress 3.2 でカテゴリーアーカイブだったら表示する件数を5件にする
function category_display_five_articles( $wp_query ) { global $wp_the_query; if ( ( $wp_the_query === $wp_query ) && $wp_query->is_category() ) { $wp_query->set( 'posts_per_page', 5 ); } } add_action( 'pre_get_posts', 'category_display_five_articles' );
のように書けば古いバージョンでもバグが起こりにくい記述をすることができますね。
「3.3の新しい関数 is_main_query を使おう」への5件のフィードバック