CommentOut

【PHP】WordPressで記事一覧を取得する方法(投稿、固定ページ、カスタム投稿タイプを含む) 【PHP】WordPressで記事一覧を取得する方法(投稿、固定ページ、カスタム投稿タイプを含む)

【PHP】WordPressで記事一覧を取得する方法(投稿、固定ページ、カスタム投稿タイプを含む)

公開日:  最終更新日:

私はWordPressで記事一覧を取得するのは、もう慣れたもんですが、それでも細かい条件の指定方法などを結構忘れてて、よく調べたりします。
このページを訪れた諸兄らもそのような境遇ではなかろうか。
今回はWordPressで記事一覧を取得する方法をまとめました。

WordPressの記事一覧を取得するPHPの関数は3種類ある

まず、今回はWordPressのテーマ内でPHPを使って記事一覧を取得する方法を紹介するのですが、PHPで記事一覧を取得できる関数は3種類存在します。

  • WP_Query
  • get_posts
  • query_posts(非推奨)

query_postsは非推奨になっていますが、残りのWP_Queryとget_postsはどちらを使っても構いません。

WP_Queryでの記事一覧の取得

<?php
$query_result = new WP_Query(array(
    'post_type'    => 'post',
    'post_status'  => 'publish',
    'orderby'      => 'date',
    'order'        => 'DESC'
)); ?>
if ($query_result->have_posts()): ?>
    <ul class="news_list">
        <?php while($query_result->have_posts()): $query_result->the_post(); ?>
            <li>
                <a class="news_block" href="<?php the_permalink(); ?>">
                    <time><?php echo get_time('Y/m/d'); ?></time>
                    <?php echo get_the_title(); ?>
                </a>
            </li>
        <?php endwhile; ?>
    </ul>
<?php else: ?>
    <?php // 条件に一致する記事が無かった場合 ?>
    <p>現在掲載中のお知らせはありません。</p>
<?php endif; ?>

ちなみに、while~endwhile;の内部についてはテンプレート化するのがオススメです。
テンプレート化する場合は以下の通りです。

【new_list.php】

<?php
$query_result = new WP_Query(array(
    'post_type'    => 'post',
    'post_status'  => 'publish',
    'orderby'      => 'date',
    'order'        => 'DESC'
)); ?>
if ($query_result->have_posts()): ?>
    <ul class="news_list">
        <?php while($query_result->have_posts()): $query_result->the_post(); ?>
            <li><?php get_template_part('news_block'); ?></li>
        <?php endwhile; ?>
    </ul>
<?php else: ?>
    <?php // 条件に一致する記事が無かった場合 ?>
    <p>現在掲載中のお知らせはありません。</p>
<?php endif; ?>

【news_block.php】

<a class="news_block" href="<?php the_permalink(); ?>">
    <time><?php echo get_time('Y/m/d'); ?></time>
    <?php echo get_the_title(); ?>
</a>

「なぜテンプレート化するのか?」ですが、テンプレート化しておけば、再利用性が増します
また、get_template_part()ってnews_block.php以外にnews_block-important.phpなどを作ると、別バージョンとして、get_template_part(‘news_block’, ‘impotant’);で呼び出せるようになるんです。便利~

しかも、WordPress5.5以降、テンプレートに変数を渡すことができるようになりました。
これ意外と知らない人が多いんですが、使いこなすとめちゃくちゃ便利です。
いつか詳しく説明します。

WP_Query・get_postsの引数(記事一覧の絞り込み条件)について

WP_Query・get_postsにはすんごいたくさんの条件設定ができます。
これを毎回忘れるんですよ。みんなもそうでしょ?

記事一覧取得の基本は以下のセットで良いかと思います。

<?php
$query_result = new WP_Query(array(
    'post_type'    => 'post',
    'post_status'  => 'publish',
    'orderby'      => 'date',
    'order'        => 'DESC'
)); ?>

投稿・固定ページ・カスタム投稿タイプの取得

これらの切り替えにはpost_typeを変更します。

<?php
$query_result = new WP_Query(array(
    'post_type' => 'post',  // 投稿
    'post_type' => 'page',  // 固定ページ
    'post_type' => 'works', // カスタム投稿タイプ(タクソノミー名が入ります)
)); ?>

公開状態を取得条件に指定する

デフォルトでは「公開済み」の記事しか取得しないのですが、例えばテストとして「公開済み」と「下書き」を表示したい場合などあるかと思います。
これらの条件も変更可能です。

<?php
$query_result = new WP_Query(array(
    'post_status' => 'publish',                 // 公開済み
    'post_status' => 'draft',                   // 下書き
    'post_status' => array('publish', 'draft'), // 公開済みと下書きの両方を取得したい
)); ?>

投稿カテゴリーで絞り込みする

投稿をカテゴリーで絞り込む処理は本当に頻繁に使います。
これは忘れないようにしておきましょう。

そう、忘れないでください。これは【投稿】をカテゴリーで絞り込む方法なんです。
【タクソノミー】を絞り込みたい場合はまた別の方法があるんです。

<?php
$query_result = new WP_Query(array(
    'post_type' => 'post', // 投稿カテゴリーの絞り込みなので

    'cat' => 4,                      // カテゴリーID(整数値が入ります)
    'cat' => get_category_by_slug('news')->cat_ID, // カテゴリースラッグからIDを取得して代入もできます
    'category_name' => 'news',       // 実はカテゴリースラッグでも指定できます
    'category_name' => 'news, tips', // 複数のカテゴリースラッグを指定する場合
)); ?>

ほんとに多いので、徐々に追加していきます。ごめんなさい。

query_postsが非推奨になっている理由

query_postsが非推奨になっている理由としては、メインループを書き換えてしまうためです。
対して、WP_Queryとget_postsについてはサブループで動かすため、メインループを書き換えません

メインループとサブループ

はて?メインループ?サブループ?という方は以下をご確認ください。

【メインループ】

<?php if (have_posts()): while (have_posts()): the_post(); ?>
    <!-- 記事を表示するHTMLを記述 -->
<?php endwhile; endif; ?>

【サブループ】

<?php if ($query_result->have_posts()): while ($query_result->have_posts()): $query_result->the_post(); ?>
    <!-- 記事を表示するHTMLを記述 -->
<?php endwhile; endif; ?>

この2つのコードは取得した記事一覧の情報にループ処理で1つアクセスしています。
こういう処理を『イテレータ』と呼ぶのですが、the_post();を呼ぶことで先頭から順番に記事情報を参照しています。

メインループとサブループの違いは関数をそのまま呼んでいるか、変数から呼んでいるかです。
変数($query_result)から呼んでいる場合(サブループの場合)、この変数($query_result)に記事一覧を代入したのだろうと考えられますよね?
では、メインループは何を参照しているのか・・・?

実はその点を問題視され、query_postsは非推奨となりました。
メインループっていうのは、ページを開いた時点で設定されている記事情報を参照しています。
例えば、category.phpでは、query_postsもWP_Queryもget_postsも使われていないのに、最初から上記のループが記述されています。
これはcategory.phpが参照される時は、何かのカテゴリーが参照された時なので、そのカテゴリーを含む記事一覧が自動的に取得されます。
これがメインループの記事情報です。

では、category.phpのメインループ内でquery_postsが使われた時、どうなると思いますか?
すごく簡単にどういう処理になるか説明すると、以下のようなループが存在するとして

<?php
$count = 12;
while ($count > 0) {
    $count -= 1;
}
?>

途中でquery_postsを使うということは、以下のコードに近いことをしているということになります。

<?php
$count = 12;
while ($count > 0) {
    $count -= 1;

    $count = 62354;  // 別のループを作りたいので、条件を再設定
    while ($count % 3) {
        $count = $count / 2;
    }
}
?>

ループの途中で、ループの条件が書き換えられてしまうわけですから、こんなもんおかしくなりますよね?
これがquery_postsが非推奨となった理由です。

宣伝
WordPressサイトのテンプレート編集やトラブル対応、バグ修正、簡単なJavascriptの作成(カルーセルやバリデーション等)など、小規模なスポット対応を受け付けております。
もしお困りごとがありましたら、お問い合わせフォームよりご相談ください。

この記事を書いた人

uilou

uilou

プログラマー

基本的に、自分自身の備忘録のつもりでブログを書いています。 自分と同じ所で詰まった人の助けになれば良いかなと思います。 システムのリファクタリングを得意としており、バックエンド、フロントエンド、アプリケーション、SQLなど幅広い知識と経験があります。 広いだけでなく、知識をもっと深堀りしていきたいですね。