blog

program

WordPressで押さえておきたい!get_posts,WP_Query,query_posts の違いと用例

例えばWordPressでこのようなことをしたい場合。

  • 固定ページで記事のタイトルとカテゴリを出力したい
  • 表示されるページ数を変更して出力したい

以下の、どれを使って出力するのが適切でしょうか。

  • get_posts
  • WP_Query
  • query_posts

今回は、この3つの特徴と異なる点、用例を紹介します。

それぞれの特徴

簡単にそれぞれの特徴をおさらいしましょう。

get_posts

  • テンプレートタグ
  • カスタムループを生成する際に使用(メインループに影響与えない)

・基本的な記述例

$args = array('post_type' => 'post'); 
$the_query = get_posts( $args );
foreach ( $the_query as $post ) : setup_postdata( $post );
the_title();
endforeach;
wp_reset_postdata();

テンプレートタグ/get posts

WP_Query

  • クラス
  • カスタムループを生成する際に使用(メインループに影響与えない)

・基本的な記述例

$args = array( 'post_type' => 'post' );
$the_query = new WP_Query( $args );
while ( $the_query->have_posts() ) : $the_query->the_post();
	the_title();
endwhile;
wp_reset_postdata();

関数リファレンス/WP_Query

query_posts

  • テンプレートタグ
  • メインループに影響を与える
  • 使用非推奨
$args = array( 'category_name=baseball' );
query_posts( $args );
while ( have_posts() ) : the_post();
    the_title();
endwhile;
wp_reset_query();

テンプレートタグ/query posts

現在のバージョンでメインループを変更するのに、query_postsを使用してはいけません。
理由は以下の通りです。

  • SQLクエリを再実行する
  • メインクエリを書き換えるので間違いが起こりやすい

古いバージョン等で、どうしても使わざるを得ない場合はwp_reset_queryをお忘れなく。

では、query_postsが非推奨ならば、メインループを変更するにはどうすればいいのでしょうか?

pre_get_postsを使おう

pre_get_postsはアクションフックといい、 $query->setと使うことでメインループを変更することができます。

アクションフックとは
特定のイベント発生時に実行する処理を追加すること。

買い物にいこうとした時(フック)に、ついでに牛乳を買ってきて(アクション)と頼まれたイメージで大丈夫です。

pre_get_postsの記述例

function.phpに記述します。

function exclude_category( $query ) {
    if ( !is_admin() && $query->is_main_query() ) {
    	if ( $query->is_home() ) {
        	$query->set( 'cat', '-1');
        }
    }
}
add_action( 'pre_get_posts', 'exclude_category' );

関数名は適切な名前にするとして、ポイントとなるのは3,4行目です。
3行目でどのページに条件を適用するかを指定し、
4行目で変更する内容を指定します。

今回は「home.php」であれば、「特定のカテゴリー(1)を除外した記事」を取得するように変更しています。

get_postsとWP_Queryの違い

単純に投稿データを取得するだけなら違いはありません。
get_postsは関数内でWP_Queryを使用しており、指定できるパラメーターもWP_Queryと同じです。

取得できる情報量が違う

get_postsはWP PostのWP_Post のメンバー変数の値を取得できます。 WP_Postのメンバー変数には記事に関する情報しかありません。
それに加え、WP_Queryはis_pageなど、ページに関する情報を持っています。

WP_Queryget_postsと比べWP_Queryのほうがより複雑な処理を行うことができるということを知っておきましょう。

用例

では最初に例としてあげた2つの用例を紹介します。

固定ページで記事のタイトルとカテゴリを出力したい

・WP_Queryを使う場合

$args = array( 'posts_per_page' => 3,'post_type' => 'post' );
$the_query = new WP_Query( $args );
while ( $the_query->have_posts() ) : $the_query->the_post();
	the_category(); 
	the_title();
endwhile;
wp_reset_postdata();

・get_postsを使う場合

$args = array( 'posts_per_page' => 3,'post_type' => 'post' );
$the_query = get_posts( $args );
foreach ( $the_query as $post ) : setup_postdata( $post ); 
	the_category(); 
	the_title();
endforeach; 
wp_reset_postdata();

カスタムループを生成し、投稿記事を出力するだけなのでどちらの書き方でも大丈夫です。

表示されるページ数を変更して出力したい

投稿記事のタイプが1つであれば管理画面の設定->表示設定-> 1ページに表示する最大投稿数を変更すればいいのですが、投稿記事(post_type=post)は10件、カスタム投稿(post_type=faq)では5件表示する場合は以下のように記述します。

function faq_posts_per_page( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
	} 
    if ( $query->is_post_type_archive( 'faq' ) ) {
        $query->set( 'posts_per_page', '5' );
    }
}
add_action( 'pre_get_posts', 'faq_posts_per_page' );

メインループを変更したいのでpre_get_postsを使います。

まとめ

WordPressクエリー比較表

pre_get_postsを含めると記述例は4つ紹介したのですが、 カスタムループはWP_Query(もしくはget_pots)、メインループはpre_get_postsを使うので、実際は2つの違い、使い方を理解しておけば大丈夫です。

もし迷ったときは用例、まとめを参考にして頂ければ嬉しいです!