「WordPressのトップページに、新着記事数件を表示する」get_postsのサンプルコードをあげとく

2013年7月22日

※2018.03.01追記:4年半経ちましたが、今のところはおおむねこの記事のままで大丈夫と思ってます。定期的にチェックするのは大事。


今年に入ってから、「クエリ変更はquery_postsかpre_get_postsか」という話題がWordPress中級者以上の間では盛り上がっていましたが、初心者コピペWordPressユーザーの多くの方には「お前ら何を言っているんだ」ということでしょう。
実際、WordPress日本語フォーラムに投稿される質問の中でも、必要ないところでquery_postsを使って表示がおかしなことになっているケースがあとを絶ちません。

古い記事が検索上位に出ている現状

なぜ同じようなトラブルが減らないのかといえば、Googleで「WordPress 新着記事」「WordPress 新着情報」などのワードで検索した時、上位に表示されている記事が結構古いものが多いのにもかかわらず、新しいユーザーさんがそのコードをコピペしてしまうことが原因だと考えています。
さらにその古い記事を見てカスタマイズをした初心者さんが、「この方法でできました!」と、元記事へのリンクを添えて古いままのコードを紹介するため、元記事の影響力はどんどん強くなっていきます。

誤解しないでいただきたいのは、決して元ネタとなった記事を批判しているわけではありません。
むしろ2年も3年も4年も前に書いた記事が今でも愛されているというのは尊敬に値しますし、ブロガー冥利に尽きることだと思います。

さらに、それを参考にした初心者さんをDisってるわけでもありません。
自分も、最近は1本の記事を書くのにかなり精査してからじゃないと書けなくなりましたが、このブログを始めた当初の記事は先輩ブロガーさんの記事をコピペして試したみた記事がほとんどでした。
今でもよそのブログから拾ってきたコードにお世話になることは多いので、コピベが必ずしも悪いことではないです。

正しいものは変わっていく

しかしながら私が言いたいのは、時は移りゆくということです。
とくにこのWeb業界というのは吉野川やナイアガラの滝のような激流であり、昨日まで正しかったことが今日はもう間違いだったりすることもあるわけです。
実際私が過去に書いた記事も、もう使えないものが結構あります。(でも直してなかったりしててごめんなさいごめんなさい)

ということで、前置きがとっても長くなりましたが、主題の通り「2013年7月現在、WordPressのトップページに、新着情報何件を表示させる」ためコピペするコードとして、一番トラブルが少なそうなのはこんな感じかなー、というのをサンプルとして挙げておきます。

初心者さんが使うなら’get_posts’

あなたが使うべきなのはquery_postsではありません。pre_get_postsのことも一旦忘れていいです。new WP_Queryもとりあえずは棚上げします。
get_postsを習得してから、他を覚えればいいです。

「WordPress 新着記事」とかで検索して、「query_postsを使いましょう」と書いてあったらその記事は読まなくて良いです。

get_postsはシンプルです。
いやシンプルというと語弊があり、裏で働いているWordPress内部のこびとさんはいっぱいいるのですが、初心者さん的にはあまり小難しいことを考えなくていいのです。

  • ページ送り機能に影響を与えません。
    query_postsを使って「2ページ目以降も同じ内容が表示されちゃう!」という心配がありません。
    ※そもそもget_postsは「指定件数分表示するだけ」なので、ページ送りを使うケースは想定してません。
  • 基本どこでも使えます。
    サイドバーでも固定ページでもアーカイブページでも、本来の表示に影響してしまう失敗が比較的少ないです。

1. 基本となる書き方

トップページ用のテンプレートファイルのお好きな位置に、以下のコードを貼り付けます。
index.phpをそのまま書き換えるのではなく、home.phpやfront-page.php、または任意のページテンプレートを作成することをおすすめします。

<?php
	$newslist = get_posts( array(
		//ここに取得条件を色々書く
	));
	if( $newslist ):
	?></pre>
<dl><?php
	foreach( $newslist as $post ):
		setup_postdata( $post );
		?>
		<dt><?php the_time('Y年n月j日'); ?></dt>
		<dd><a href="<?php the_permalink(); ?>"> <?php the_title(); ?></a></dd>
	<?php
	endforeach;
	wp_reset_postdata();
	?></dl>
<?php else: ?>
<p>あてはまる情報はまだありません。</p>
<?php endif; ?>

※上記コード内の変数「$newslist」は私が勝手に名付けたものなので、任意の名前に変えてOKです。
「$posts」と「$post」を使って説明しているケースが多いですが、変えてもOKなのです。(≫参考ページ
今回は「$posts」のみを別名に変えています。(通常のテンプレートタグをそのまま使いたいため。setup_postdataがポイントなのですが本題から逸れて初心者さん向けじゃなくなるため割愛。)

なお上記 「//ここに取得条件を色々書く」の部分に条件を何も書かない場合、どういう表示になるかというと

  • 通常の「投稿」の中から公開済みのものを
  • カテゴリーやタグなどで絞りこまずに
  • 投稿日の新しい順に
  • 最大5件まで表示

します。
では、上記 「//ここに取得条件を色々書く」の部分に色々書いてみましょう。

2. 「news」カテゴリーから10件分表示し、日付とタイトルを表示

これはよくあるやつですね。


<?php
   $newslist = get_posts( array(
    'category_name' => 'news', //特定のカテゴリースラッグを指定
    'posts_per_page' => 10 //取得記事件数
   ));
   if( $newslist ):
?>
<dl><?php
   foreach( $newslist as $post ):
   setup_postdata( $post );
?>
<dt><?php the_time('Y年n月j日'); ?></dt>
<dd><a href="<?php the_permalink(); ?>"> <?php the_title(); ?></a></dd>
	<?php
	endforeach;
	wp_reset_postdata();
	?></dl>
<?php else: ?>
<p>あてはまる情報はまだありません。</p>
<?php endif; ?>

※「category_name」じゃなくて「cat」も使えますが、「cat」を使う時はスラッグじゃなくてカテゴリーID(数字)で指定しないといけないため、個人的には「category_name」をいつも使っています。

3.「goods」カスタム投稿タイプの中で、「color」というカスタムタクソノミーで「red」というタームに分類付けされている記事の中からランダムに3件分表示し、タイトルとアイキャッチ画像を表示

ちょっと条件がわかりづらいんですが、例えばWordPressを企業や店舗のサイトとして使っている場合にけっこう活躍します。
ブログや新着情報とは別に「商品紹介」というカスタム投稿タイプを作っておいて、その中で「カラー」「サイズ」などのカスタムタクソノミーでさらに分類。
以下では、「カラーが赤の商品をランダムで表示」という条件で表示します。

<?php
$goodslist = get_posts( array(
       'post_type' => 'goods', //特定のカスタム投稿タイプスラッグを指定
       'taxonomy' => 'color', //特定のカスタムタクソノミースラッグを指定
       'term' => 'red', //特定のカスタムタクソノミー内のタームスラッグを指定
       'orderby' => 'rand', //何順で並べるか
       'posts_per_page' => 3 //取得記事件数
  ));
if( $goodslist ): ?>
<ul><?php foreach( $goodslist as $post ):
setup_postdata( $post );
?>
<li><a href="<?php the_permalink(); ?>"> <?php the_post_thumbnail(); ?></a> <a href="<?php the_permalink(); ?>"> <?php the_title(); ?></a></li>
	<?php
	endforeach;
	wp_reset_postdata();
	?></ul>
	<?php else: ?>
<p>あてはまる情報はまだありません。</p>
<?php endif; ?>

※dlじゃなくてulタグに変えてみました。
 orderbyには他に、’title’(記事タイトルの文字列順)、’author’(著者順)、’parent’(親記事のID順)、’modified’(最終更新日順)などなどあります。
※「赤」または「青」の商品、という感じで複数のタームを指定する場合は、
 'term' => 'red''terms' => array( 'red', 'blue' ) という感じの配列にします。
「term」ではなく「terms」と複数形なことに注意してください。自分は初めて使った時これでハマりました。。。

4. 「goods」カスタム投稿タイプの中で、「color」というカスタムタクソノミーで「red」というタームに分類付けされている、かつ「size」というカスタムタクソノミーで「small」というタームに分類付けされている記事の中から、タイトルとアイキャッチ画像を表示

上と似てるんですが、条件を複数指定するためにtax_queryを使っています。

<?php
$goodslist = get_posts( array(
       'post_type' => 'goods', //特定のカスタム投稿タイプスラッグを指定
       'tax_query' => array( //複数条件指定
              'relation' => 'AND', //AND(かつ)かOR(または)
                 array(
                      'taxonomy' => 'color',
                      'field' => 'slug', //スラッグで指定
                      'terms' => 'red'
                     ), array(
                      'taxonomy' => 'size',
                      'field' => 'slug',
                      'terms' => 'small'
                    )
        ),
       'orderby' => 'rand', //何順で並べるか
       'posts_per_page' => 3 //取得記事件数
  ));
if( $goodslist ):
?>
<ul><?php 
foreach( $goodslist as $post ):
setup_postdata( $post );
?>
<li><a href="<?php the_permalink(); ?>"> <?php the_post_thumbnail(); ?></a> <a href="<?php the_permalink(); ?>"> <?php the_title(); ?></a></li>
	<?php
	endforeach;
	wp_reset_postdata();
	?></ul>
	<?php else: ?>
<p>あてはまる情報はまだありません。</p>
<?php endif; ?>

ここでも上記同様、「term」ではなく「terms」と複数形なことに注意してください。自分は案の定tax_queryを初めて使った時またハマりました。。。
詳しくは@jim0912さんによるWordPressの新機能 複数タクソノミークエリーまとめ | Simple Colorsの記事がおすすめ。

5. 「recommend」というカスタムフィールドの中に「おすすめ」という値が入っている記事を全件表示

カスタムフィールドと組み合わせると、さらに複雑な条件設定ができます。

<?php
    $recommend = get_posts( array(
        'meta_query' => array( array( //カスタムフィールド指定
             'key' => 'recommend', //カスタムフィールドのキー名
             'value' => 'おすすめ' //そのフィールドに入れられている値名
        )),
        'posts_per_page' => -1 //すべて取得
      ));
  if( $recommend ):
?>
<ul><?php
  foreach( $recommend as $post ):
  setup_postdata( $post );
?>
<li><a href="<?php the_permalink(); ?>"> <?php the_title(); ?></a></li>
	<?php
	endforeach;
	wp_reset_postdata();
	?></ul>
	<?php else: ?>
<p>あてはまる情報はまだありません。</p>
<?php endif; ?>

※全件表示したいときに、たまに「100」とか「9999」とか大きめの数字を入れて頑張ってるのを見かけますが、「-1」で全件取得になります。

5. タイトルや日付だけでなく、本文も表示させたい

本文を表示させるケースではちょっと注意が必要です。

<?php
   $newslist = get_posts( array(
    'category_name' => 'news', //特定のカテゴリースラッグを指定
    'posts_per_page' => 3 //取得記事件数
  ));
   if( $newslist ):
?>
<dl><?php 
    foreach( $newslist as $post ):
    setup_postdata( $post );
?>
<dt><?php the_time('Y年n月j日'); ?></dt>
<dd><a href="<?php the_permalink(); ?>"> <?php the_title(); ?></a> <?php global $more;
	$more = false;
	the_content('≫続きを読む');
	?></dd>
	<?php
	endforeach;
	wp_reset_postdata();
	?></dl>
	<?php else: ?>
<p>あてはまる情報はまだありません。</p>
<?php endif; ?>

※moreタグ(続きを読む)を正しく表示させるために、global $more; $more = false;($more = 0;も同義)を追記する必要があります。

個人的によく使うものまとめ

必要なもののコメントアウトを外して使う感じで。

<?php
   $newslist = get_posts( array(
  //'category_name' => 'slug', //特定のカテゴリースラッグを指定
  //'tag' => 'slug', //特定のタグスラッグを指定
  //'post_type' => 'slug', //特定のカスタム投稿タイプスラッグを指定
  //'taxonomy' =>'slug', //特定のカスタムタクソノミースラッグを指定
  //'term' =>'slug', //特定のカスタムタクソノミー内のタームスラッグを指定
  //'terms' => array( 'slug1', 'slug2' ), //特定のカスタムタクソノミー内のタームスラッグを複数指定
  /*'tax_query' => array( //複数条件指定
       'relation' => 'AND', //AND(かつ)かOR(または)
         array(
            'taxonomy' => 'color',
             'field' => 'slug', //スラッグで指定
             'terms' => 'red'
         ), array(
             'taxonomy' => 'size',
             'field' => 'slug',
             'terms' => 'small'
         )),*/
  /*'meta_query' => array( array( //カスタムフィールド指定
       'key' => 'keyname', //カスタムフィールドのキー名
       'value' => 'value' //そのフィールドに入れられている値名
       )),*/
  //'orderby' => 'modified', //何順で並べるか
  //'order' => 'ASC', //昇順にしたいとき
  'posts_per_page' => 10 //取得記事件数
  ));
   if( $newslist ):
?></pre>
<dl><?php
    foreach( $newslist as $post ):
    setup_postdata( $post );
?>
<dt><?php the_time('Y年n月j日'); ?></dt>
<dd><a href="<?php the_permalink(); ?>"> <?php the_title(); ?></a> <?php global $more;
	$more = false;
	the_content('≫続きを読む');
	?></dd>
	<?php
	endforeach;
	wp_reset_postdata();
	?></dl>
	<?php else: ?>
<p>あてはまる情報はまだありません。</p>
<?php endif; ?>

その他の条件を指定したい時

Codexを見て、必要なパラメータを追記してください。

実はget_postsのページは情報が少ないので、自分はquery_postsのページWP_Queryのページを参照することが多いです。
現在はget_posts、query_posts、WP_Queryは同じパラメータが使えるようになっているので、情報が足りない場合はこちらで補っています。

さいごに

この記事もいつかは古くて使い物にならなくなります。
その時はあなたが最新のコードをぜひ自分のブログで紹介してください。

#補足
時は移りゆくとは言いましたが、2011年の時点でこの記事を書いてるkzさんはやっぱりイケメンだと改めて思いました。

さらっと「メインループそのものを変更したいだけなら pre_get_posts アクションを使うと良いでしょう。」って書いてるし。
2年がかりで、ようやくこの記事の意味がわかるようになってきました。継続は力なり。