もうquery_postsは呼ばない

もうquery_postsは呼ばない - フィルター処理を使ってquery_posts関数の二重呼び出しをやめる

説明

トップページやカテゴリーページで標準の条件に少し手を加えた投稿情報を表示するケースがある。そんな時、テンプレートファイルの先頭でquery_posts関数を呼び出して投稿情報を再抽出していたのだが、フィルター処理をうまく使えばquery_posts関数を呼び出さなくても大丈夫みたいだ。
そもそもなぜこんなことを考えたかというと、テンプレートファイルの先頭でquery_posts関数の呼び出しは、それなりに時間がかかっているから。WordPressのシステム自体が最初に投稿情報を抽出する際に条件を変更できれば、query_posts関数の呼び出しも必要なくなり、結果としてページを表示するまでの時間も短縮できることになる。
query_postsのフィルター
WordPressのフィルター処理は特定の関数の結果に影響を与えるもので、query_posts関数には多くのフィルターが用意されている。使用頻度が高い(比較的使い勝手がいい?)と思われるフィルターには次のようなものがある。
フィルター意味
posts_joinJOINの指定
posts_whereWHEREの指定
posts_groupbyGROUP BYの指定
posts_orderbyORDER BYの指定
post_limitsLIMITの指定
posts_fields抽出カラムの指定
これらは投稿情報を抽出するSQL文を構成するパーツに対応しており、SQLについて知識がある方ならそれぞれが何なのか想像できるだろう。
トップページに表示する投稿情報数を変える
具体例があった方がピンくると思うので、トップページ(フロントページ)に表示する投稿情報の件数を変更する例を最初に紹介する(各ソースコードは、原則自身のテーマのfunctions.phpに記載するものとし、各関数名mythemeの部分の部分は適宜変更するものとして読み進めてほしい)。
まずquery_posts関数を呼び出す場合は次の指定になる。
query_posts( 'posts_per_page=5' );
これをフィルターで対応する場合は、次のように指定すればいい。
add_action( 'after_setup_theme', 'mytheme_setup' );

function tpsalon_setup() {
	add_filter( 'post_limits', 'mytheme_post_limits' );
}

function mytheme_post_limits( $arg ) {
	global $wp_query;
	if ( $wp_query->is_home ) {
		$arg = 'LIMIT 0, 5';
	}
	remove_filter( 'post_limits', __FUNCTION__ );
	return $arg;
}
流れを簡単に説明すると、
1.after_setup_themeアクションの処理としてquery_posts関数のフィルターであるpost_limitsフィルターとしてmytheme_post_limits関数を登録。
2.WordPressシステムが最初にquery_posts関数を呼び出した際に、登録したmytheme_post_limits関数が呼び出される。
3.mytheme_post_limits関数では、グローバル変数$wp_queryを参照して呼び出しがトップページか調べ、トップページの場合はパラメータ$argの内容を'LIMIT 0, 5'(先頭から5件のみ取得)に変更。
4.誤動作を防ぐため、フィルターからmytheme_post_limits関数を削除。
5.パラメータ$argを返す。
といった流れになる。
mytheme_post_limits関数のパラメータ$argには「表示設定」の「1ページに表示する最大投稿数」で指定した値(デフォルトであれば10)を含んだ文字列('LIMIT 0,10')が格納されており、ここではトップページの場合のみ5件に変更していることになる。なおグローバル変数$wp_queryは、query_posts関数の呼び出しによって生成・更新されるWP_Queryのオブジェクトで、is_homeプロパティは呼び出しがトップページかどうかを示している。この値はis_home関数で取得できるものと同じである。
日付アーカイブページの表示順を昇順にする
今度は日付アーカイブページで投稿情報が表示する順番を投稿日時の新しい順から古い順に変更してみる。
まずquery_posts関数を呼び出す場合は次の指定になる。
query_posts( 'order=ASC' );
これをフィルターで対応する場合は、次のように指定すればいい。
add_action( 'after_setup_theme', 'mytheme_setup' );

function tpsalon_setup() {
	add_filter( 'posts_orderby', 'mytheme_posts_orderby' );
}

function mytheme_posts_orderby( $arg ) {
	global $wp_query;
	if ( $wp_query->is_date ) {
		$arg = str_replace( 'DESC', 'ASC', $arg );
	}
	remove_filter( 'posts_orderby', __FUNCTION__ );
	return $arg;
}
流れを説明すると、
1.after_setup_themeアクションの処理としてquery_posts関数のフィルターであるposts_orderbyフィルターとしてmytheme_posts_orderby関数を登録。
2.WordPressシステムが最初にquery_posts関数を呼び出した際に、登録したmytheme_posts_orderby関数が呼び出される。
3.mytheme_post_limits関数では、グローバル変数$wp_queryを参照して呼び出しが日付アーカイブページか調べ、日付アーカイブページの場合はパラメータ$argの中身の'DESC'を'ASC'に変更。
4.誤動作を防ぐため、フィルターからmytheme_posts_orderby関数を削除。
5.パラメータ$argを返す。
といった流れになる。基本的な流れは先ほどと同じで、ここではstr_replaceによってパラメータ$argの内容を更新している。ちなみに呼び出し時点の$argの内容は'wp_posts.post_date DESC'となっている('wp_'の部分はWordPressをインストールした際のプレフィックスによって変わる)。
フィルターの使いこなしにはSQLの知識が欠かせない
ここまで簡単な使用例を2つ紹介した。各テンプレートファイルでquery_posts関数を呼び出した方が簡単なのは確かだが、より効率よくリクエストされたページを表示するならquery_posts関数のフィルターで対応するほうが望ましいと考える。
query_posts関数のフィルターを使いこなすにはSQLの知識も欠かせない。それはより実践的なシーンでは、いくつかのフィルターを組み合わせることになるからだ。というわけで、次回は他のフィルターや複数のフィルターを組み合わせについて紹介してみたい(需要があるか不安ではあるが)。

関連

  • add_action - アクション関数を追加する
  • add_filter - フィルター関数を追加する
  • is_date - 日付アーカイブページか調べる
  • is_home - ホームページか調べる
  • query_posts - 条件を指定して投稿情報をロードする
  • remove_filter - WordPressタグに登録されているフィルターを削除する

お勧めコンテンツ

get_edit_user_link(2012年12月12日 登録)

string get_edit_user_link( [ int $user_id ] )
ユーザ情報ページのURLを取得する。

home_url(2010年6月9日 登録)

string home_url( [ string $path = '' [ , string $scheme = null ] ] )
現在のブログ(サイト)のホームURLを取得する。ホームURLは、管理者ページの「設定」-「一般」の「サイトのアドレス(URL)」のこと。

get_language_attributes(2015年8月26日 登録)

string get_language_attributes( string $doctype = 'html' )
HTMLタグの属性を取得する。

is_sticky(2014年2月21日 登録)

bool is_sticky( [ int $post_id = 0 ] )
投稿が「先頭に固定表示(sticky)」か調べる。

get_site_option(2010年7月5日 登録)

mixed get_site_option( string $option [ , mixed $default = false [ , bool $use_cache$deprecated = true ] ] )
サイトオプションの値を取得する。

最終更新日時 : 2011-09-27 20:56