
get_postsとWP_Query それぞれの特徴と違いをまとめてみました
get_postsとWP_Queryはいずれもサブループ中に必要な情報を表示させる命令です。get_postsと比べるとWP_Queryの方が記述量が増えます。
get_postsは投稿記事の配列情報のみを取得し、WP_Queryはそれ以外の様々なクエリ情報も取得します。
いずれもパラメータ値で条件を設定でき、the_postの方式が使えます。リセットにはwp_reset_postdata()を使いましょう。
サブループに使用するget_postsとWP_Query
「get_posts」および「WP_Query」は、管理者がWordpressのデータベース情報を取得できる記述命令です。
いずれもWordpressで実行されるメインループとは別のループ、つまりサブループを作る際に使われます。
get_postsは一般的に「メソッド」と呼ばれ、WP_Queryは「クラス」と呼ばれます。
・get_posts…メソッド
・WP_Query…クラス
両者の共通点
両者には共通点が多くあり、投稿記事を扱うだけならどちらでも問題はありません。
・サブループを作成する際に使用される
・投稿記事データを取得する事ができる
明確な違い
get_postsでは、投稿記事以外のデータを扱う事はできません。
投稿記事だけを扱うならget_posts、それ以外のデータも利用するならWP_Queryと決まっています。
・投稿記事の出力限定…get_posts
・それ以外のデータも出力…WQ_Query
get_postsの特徴
まずは「get_posts」の特徴について紹介しましょう。
get_postsの書き方例
<?php // 投稿のパラメータ設定 $args = array( 'post_type' => 'my_posts', 'posts_per_page' => 3, 'category' => '10', ); // クエリオブジェクト取得 $my_posts = get_posts($args); // ループの開始 foreach ($my_posts as $val): global $post; $post = $val; // globalpost情報の取り出し setup_postdata($post); // 情報出力 <h1><?php the_title(); ?></h1> <p><?php the_content(); ?></p> // リセット <?php endforeach; wp_reset_postdata(); ?>
上記はthe_postsの記述を利用しています。
get_postsの記述
get_postsは、投稿の情報を持った配列を返すメソッドなので、ループには「foreach」を使って出力していきます。
WP_Queryと違って、have_posts()で投稿の有り無しの判定をおこなう必要がありません。
get_postsの方がコードがシンプルになる事は間違いないですね。
get_postsは投稿記事しか取得できない
get_postsの最大の違いは「投稿記事」に関する情報しか取得ができない事でしょう。
固定ページやそれ以外のクエリ情報などを取得する事ができない訳ですね。
条件に合う投稿が存在しない場合は空のオブジェクトが返され、そのページ要素自体が非表示となります。
※WP_Queryの場合は条件に合う記事がなくても、表示されているページに関する情報は取得されます。
WP_Queryの中で実行されている
実はget_postsは、Worpdressのシステムが動かす大枠のクエリ(WP_Query)の中で実行されているメソッドです。
Wordpressの稼働中は、常にWP_Queryオブジェクトが作成された状態になります。
get_postsはそのオブジェクトの中で、実行結果だけを受け取っている訳です。
ですのでget_postsは単体で動いているのではなく、WP_Queryの中で実行されている事になりますね。
WP_Queryの特徴
では次にWP_Queryの特徴を見ていきましょう。
WP_Queryの書き方例
<?php $args = array( 'post_type' => 'blog', 'posts_per_page' => 15, 'no_found_rows' => true; ); // クエリオブジェクト取得 $blog = new WP_Query( $args ); if ( $the_query->have_posts() ) { // ループの開始 while( $the_query->have_posts() ) { $the_query->the_post(); ?> <h1><?php the_title(); ?></h1> <p><?php the_content(); ?></p> <?php } // グローバルの$postの値を、メインクエリの値に戻す wp_reset_postdata(); } ?>
WP_Queryはメインループと同じように、取得条件やそれに付随する機能を利用する事ができます。
これはメインループ自体がWP_Queryによって生成されているためですね。
それに対してget_posts()は、取得された情報しか扱う事ができません。
WP_Queryの記述
WP_Queryは、投稿の情報を持ったインスタンスを生成するクラスです。
表示する投稿があるかどうかを「have_posts()」でチェックし、投稿があれば「the_post()」でpostプロパティを取得します。
ループには「while」を使い、自由に表示する事ができます。
get_postsと比べると若干記述量が多いと言えますね。
WP_Queryは投稿データ以外のページ情報も取得できる
WP_Queryは、投稿記事以外に固定ページなど表示しているページ自体の情報も取得できます。
ここがget_postsとの一番大きな違いといえるでしょう。
表示されているページの種類(投稿ページ or 固定ページ)や、パーマリンクや管理者名、カテゴリ名などの様々なクエリ情報も取得できます。
the_postメソッドが利用できる
get_posts・WP_Queryのいずれも、「the_post」を使った表現ができます。
<?php the_title(); ?>
<?php the_content(); ?>
<?php the_permalink(); ?>
タイトルや本文を表示する際、上記の様な表記をよく使う事でしょう。
これらは全て、データを所持する$GLOBALS['post']のプロパティから引っ張ってきた、WP_Queryのメソッドの記述です。
WP_Queryならthe_post()だけでOKですが、get_postsでもsetup_postdata($post)により利用できます。
これによりどちらの方法でも、データの出力時にthe_postの表現が使える訳です。
wp_reset_postdata()によるリセット
どちらの方法もループ終了時に使うのが、wp_reset_postdata()です。
いずれの場合でデータを出力しても、それらは全てサブループでありメインループの実行中の「差し込み操作」です。
この差し込みにより、途中でデータを所持する$GLOBALS['post']の中身が置き換えられてしまう訳です。
これをメインループの中身に戻すのが、wp_reset_postdata()関数です。
reset_postdata()とwp_reset_postdata()
似たような関数にreset_postdata()があります。
reset_postdata()
reset_postdata()は自身が保持しているpostプロパティ情報を、$GLOBALS['post']に戻す関数です。
つまりreset_postdata()を実行すると、メインループのpost情報がサブループのpostプロパティに置き換わってしまう訳です。
こうなるとメインループのデータが正常に動きません。
wp_reset_postdata()
それに対してwp_reset_postdata()は、メインループのインスタンス情報を$GLOBALS['post']に戻す関数です。
メインループのインスタンスを保持しているのは、$GLOBALS['wp_query']ですね。
この$GLOBALS['wp_query']が所有している値を、$GLOBALS['post']に戻す事になります。
・reset_postdata()…自身のpostプロパティを$GLOBALS['post']に戻す
・wp_reset_postdata()…メインループのプロパティを$GLOBALS['post']に戻す
メインループの情報に戻す場合は、メインループのインスタンスである$GLOBALS['wp_query']情報に戻す必要があります。
リセット時にはwp_reset_postdata()を使いましょう。
query_posts()は使わない
もう一つサブループを作る方法として、query_posts()を利用する方法がありました。
この関数は、先程のお話に出たメインループの$GLOBALS['wp_query']自体に、変更を加えてしまう特徴があります。
ですので、サブループ終了時にメインループとなる$GLOBALS['wp_query']の情報を元に戻す作業が必要になります。
ですので最近は、サブループを作る際にquery_posts()は使わないようになっています。
まとめ:どちらを使うべきか
結局どちらを使うのかはその用途によって変わると思います。
コードのシンプルさと処理速度を追求するのなら、get_postsで良いでしょう。
それに対し様々なデータを出力するのなら、WP_Queryを採用するべきです。
豊富な条件パラメータ値
get_postsもWP_Queryも、最初に取得条件を細かく設定する事ができます。
この取得条件となるパラメータ名は、両者おおむね共通です。
post_type | カスタム投稿名 |
---|---|
posts_per_page | 出力したい数字 |
category | カテゴリー |
orderby | 並びの基準 |
order | 昇順降順 |
tax_query | カスタムタクソノミー |
速さを追求する場合
投稿記事の出力でWP_Queryを使う場合、パラメータで「'no_found_rows' => true」の記述を入れる事が推奨されています。
この記述がないと処理が格段に遅くなるためです。
WP_Queryのコード
<?php $args = array( 'no_found_rows' => true, 'post_type'=>'post', 'posts_per_page' => 100, 'post_status' => array('publish'), ); $the_query = new WP_Query( $args ); if ( $the_query->have_posts() ) { while( $the_query->have_posts() ) { $the_query->the_post(); ?> <?php the_title(); ?> <?php } wp_reset_postdata(); } ?>
それに対しget_postsの場合、「'no_found_rows' => true」の初期値は「true」です。
ですので記述自体を書く必要がありません。
get_postsのコード
<?php $args = array( 'post_type'=>'post', 'posts_per_page' => 100, 'post_status' => array('publish'), ); $my_posts = get_posts( $args ); if ( $my_posts ) { global $post; foreach( $my_posts as $post ) { setup_postdata( $post ); ?> <?php the_title(); ?> <?php } wp_reset_postdata(); } ?>
その分だけget_postsの方がコードは少なくなりますね。
WP_Queryでもちゃんと「'no_found_rows' => true」を設定すれば、get_postsとそれ程処理の差はありません。