投稿一覧を表示させるメインループの使い方とサブループとの違い

プログラミングの「ループ」とはとある処理を特定の条件を満たすまで繰り返すことを指します。

WordPressで「ループ」は投稿を繰り返し表示させることを指し、投稿記事一覧や詳細ページなどで使われています。

ループとそれに伴うクエリについて、またメインループとサブループと呼ばれる2つのループがあるので、その違いについても記していきます。

これらについてよく理解していなくてもサイトを作ることができるのがWordPressの良いところでもあります。
ただループの仕組みや設定項目を詳しく知っていた方が時間をかけずに意図した通りに表示させやすいですし、カスタマイズの幅が広がります。

メインループの書き方だけを確認したい方は目次の「ベーシックなメインループの書き方」をクリックしてください。

WordPressを使うなら理解しておきたいループとクエリ

投稿記事に関する情報など、データを取得・出力するために繰り返す処理のことをループと言います。

アーカイブ・カテゴリーページの一覧やサイドバーに表示される新着記事、人気記事や関連記事の一覧など、また1つの記事情報だけが必要な詳細ページでもWordPressではループを利用して表示しています。

クエリとは

WordPressのループについて調べると、セットで「クエリ」という言葉を使われていることが多いので、クエリが何なのかも知っておきたいところです。

クエリはデータベースに対して処理要求(問い合わせ)をするものです。

投稿した情報はデータベースに保存されています。投稿記事を表示させるには、データベースから表示させたい記事を指定しなければなりません。クエリによって表示させたい記事の条件を絞り込んでデータベースにその情報を要求することができます。

WordPressでは簡単にURLをカスタムできるので、あまり設定しないかもしれませんが、作成した記事の本来のURLは、パーマリンク設定の「基本」の形です。

https://example.com/?p=1234

この形のURLを https://example.com/post-name/ というようなユーザーが見やすい形に簡単にカスタムできるようになっており、その形で設定している方が多いと思います。

基本の形を見てみると取得される内容が分かりやすいです。「?」以降にある内容が記事を取得するための条件になっています。これがクエリです。
上記の形だと「IDが1234の記事」を条件にデータベースへリクエストして、情報を読み取っています。

そして取得したデータを $wp_query というオブジェクトに保存します。そして保存された情報を繰り返し引き出すことがループです。

WordPressではアクセスしたURLによって決められた投稿データを取得しています。
URLによって決められた情報や条件を「メインクエリ」、それ以外にこちらから指定するものを「サブクエリ」と言います。

メインループとサブループの違い

ループは使用するクエリの違いによって呼び分けられています。
メインクエリを使ったループを「メインループ」、サブクエリを使ったループを「サブループ」と言います。

URLによって自動的に決められている条件がメインクエリ、それ以外で表示させたい記事の条件を指定するのがサブクエリなので、ループもそれに併せて以下のように使い分けられます。

自動で決められているデータを表示させる → 「メインループ」
決まったデータ以外を表示させる → 「サブループ」

メインループの使用

メインループを使用するのは、全記事の一覧を表示する、それぞれのカテゴリーページで一覧を表示させる時などです。

ループ(繰り返し)という言葉から複数の記事を表示させるもののように感じますが、1件しかなくてもループ処理が働きます。記事の詳細ページ(single.pnpやpage.phpで表示されるページ)もメインループ機能により表示させています。(ループした結果、1件しか該当するデータがないためそれを表示)

使用するテンプレートファイルによっては後述する while_post() といったコードの記述がなくてもメインループが取得されます。single.pnp なら該当の投稿記事の内容、category.php なら該当カテゴリーの全てがデータに含まれます。

サブループの使用

サブループを使用するのは、メインループで表示されるもの以外を表示させたい場合。とあるカテゴリーページで、別のカテゴリー記事も表示させたい、個別ページに関連記事などを表示させたい、カスタム投稿タイプの記事一覧を表示させたいと言った場合などがあげられます。

ここではメインループの書き方を紹介していきます。

ベーシックなメインループの書き方

メインループでは、特に「どの記事の情報が必要か」ということは記載しません。メインクエリによってすでにデータがリクエストされているからです。

メインクエリで表示できる投稿を表示させるときはこのベーシックな形でOK。

<?php if(have_posts()): ?>
  <!-- もし投稿があって一度のみ何かをしたいときはココ -->
  <?php while(have_posts()): the_post(); ?>
  <!-- 投稿内容を繰り返し処理・表示 -->
  <?php endwhile; ?>
  <!-- 投稿内容の繰り返し処理が終わって一度のみ何かをしたいときはココ -->
<?php else: ?>
  <!-- 投稿がなかったら何をするか -->
<?php endif; ?>

それぞれのコードについて説明していきます。

if(have_posts())

「もし投稿があれば」というif文です。投稿がない場合でも何かしらの処理をさせたいときに必要なコードです。

else までが投稿がある場合の処理、else の後には投稿がない場合何をするか、ということを記述します。

確実に投稿がある状態で「投稿がない場合の処理」というものがなければ、この記述は必要ありません。その場合、while ... の部分のみでOK。

<?php while(have_posts()): the_post(); ?>
  <!-- 投稿内容を繰り返し処理・表示 -->
<?php endwhile; ?>

投稿の繰り返しが必要なく、投稿があるかないかの判別だけ必要な場合はこの記述だけでOK。

<?php if(have_posts()): ?>
  <!-- もし投稿があって何かをしたい、表示させたいこと -->
<?php else; ?>
  <!-- 投稿が一つもない場合にすること、表示させたいこと -->
<?php endif; ?>

while(have_posts())

while(have_posts()) は「投稿がある分繰り返し処理をする」というものです。
endwhile までの内容がある限り、繰り返し処理をしていきます。5件の投稿データがあれば、その全てのデータを取得して表示することになります。

endwhile の後には一度だけ行いたい内容を書きます。

<?php if(have_posts()): ?>
  <?php while(have_posts()): the_post(); ?>
  <!-- 投稿内容を繰り返し処理・表示 -->
  <?php endwhile; ?>
  <!-- 投稿内容の繰り返し処理が終わって一度のみ何かをしたいときはココ -->
  <?php else: ?>
<?php endif; ?>

WordPressでは初期設定として、ループを使った際に表示される投稿数が設定されているので、変更したい場合は投稿数を変えます。
wp_querypre_get_posts などを使用して設定することもできます。

the_post()

the_post() は投稿を表示するために必要なコードで while(have_posts()) とは必ずセットで使います。

この関数は、$wp_query にある記事データを1件取り出して $post へ格納し、参照している$wp_query のデータ一覧から1件削除する、という処理をしています。
while文で繰り返すことで次々と記事を取り出し、取り出したものは削除されていきます。取り出すものがなくなったら処理も終了です。

ちなみにワードプレスで投稿内容を出力する関数はいくつかあって、the_〇〇() というものは出力関数(特定のことを表示させるための関数)です。

endwhile、endif

endwhileendif は、if文(条件分岐)の処理や、while文(繰り返し処理)が終わることを明示するものです。

波括弧「{}」を使っている場合は記述しません。この括弧の代わりにコロンと endwhile, endif といった記述を使用しています。

// endif, endwhile が不要な場合の書き方
if(have_posts()) {
  //  投稿があったらすること
  while(have_posts()) {
    // 投稿の繰り返しですること
  }
}

if(have_posts()):while(have_posts()): のようにコロンをつけている場合は必須。ないとエラーになるので、もしエラーになったらここをチェックします。

使い方例(投稿タイトルのリスト表示)

以下の内容のコード例です。

  • メインループが使用できるテンプレートファイル(single.php, category.php, archive.phpなど)に記述する。
  • もし投稿があれば、h2タグの部分を表示。その後にリンク付きの投稿タイトルを繰り返し表示させる。
  • 投稿がなければ、「記事はありません」と表示させる。
<?php if(have_posts()): ?>
  <h2>投稿のタイトルをリスト表示させる</h2>
  <ul>
  <?php while(have_posts()): the_post(); ?>
    <li>
      <a href="<?php the_permalink(); ?>">
        <h3><?php the_title(); ?></h3>
      </a>
    </li>
  <?php endwhile; ?>
  </ul>
  <?php else: ?>
  <p>記事はありません</p>
  </ul>
<?php endif; ?>

メインループの中では <?php the_〇〇() ?> と言ったテンプレートタグが使用できます。
代表的な出力テンプレートタグに以下のものがあります。

the_title()投稿のタイトルを表示
the_content()投稿の本文を表示
the_permalink()投稿のパーマリンクURLを表示
the_date()投稿の日付(投稿日または更新日)を表示
the_category()投稿のカテゴリーを表示
the_tags()投稿のタグを表示
the_excerpt()投稿の抜粋を表示
the_author()投稿したユーザー名を表示

ループを回した後にもう一度回したい

はじめに目次のように記事のタイトルだけの一覧を表示させたり一部の記事だけを表示させて、その後に全ての記事を一覧で表示させたい、といったときなどはループを2回以上回す必要があります。
しかしループで使用される $wp_query にある情報は the_post() によって削除されるため、2回目のループを回そうとしても投稿がない状態になってしまい、情報を取得することができません。

同じページの別の場所でもう一度記事情報を取得したい場合は rewind_posts() という関数を使用します。

<?php if(have_posts()): ?>
  <?php while(have_posts()): the_post(); ?>
    <!-- 投稿内容を繰り返し処理・表示 -->
  <?php endwhile; ?>
  <?php else: ?>
<?php endif; ?>

<!-- ループを巻き戻す -->
<?php rewind_posts(); ?>

<?php if(have_posts()): ?>
  <?php while(have_posts()): the_post(); ?>
    <!-- 投稿内容を繰り返し処理・表示 -->
  <?php endwhile; ?>
  <?php else: ?>
<?php endif; ?>

ループの最初や最後で違う処理をしたい

$wp_query には様々な情報が入っています。その一つに current_post というループの回数情報(最新の投稿が何番目にあるかという数字)があるので、これを利用して条件分岐をつけます。

最初だけ変える

最初の投稿はカウントが「0」なので $wp_query->current_post == 0 を指定。

<?php if(have_posts()): ?>
  <?php
    while(have_posts()): the_post();
      if($wp_query->current_post == 0):
        // 最初の違う処理
  ?>
  <?php endif; ?>
  <!-- ココには通常の繰り返し処理 -->
  <?php endwhile; ?>
<?php else: ?>
<?php endif; ?>

最後だけ変える

最後だけ変える場合は、current_post の他に post_count も使います。

post_count は投稿されている数です。その全体の投稿数から「-1」をすると最後の投稿になります。

1を引くのは、投稿数が0から数えられるからです。
例えは25コの投稿があったとすると、カウントとしては「0」が1つ目の投稿になるので、1 が 2つ目の投稿、2 が 3つ目の投稿・・・となります。

なので $wp_query->current_post から $wp_query->post_count - 1 を指定します。

<?php if(have_posts()): ?>
  <?php while(have_posts()): the_post(); ?>
  <!-- ココには通常の繰り返し処理 -->
    <?php if($wp_query->current_post == $wp_query->post_count - 1): ?>
      <!-- 最後の違う処理 -->
    <?php endif; ?>
  <?php endwhile; ?>
<?php else: ?>
<?php endif; ?>

メインループを制御する pre_get_posts

メインループの設定は、pre_get_posts を使って変更できます。
pre_get_posts はデータベースを検索する前に実行されるアクションフックです。

アクションフックはとあるイベントが発生するときに実行する処理を追加するもので、「このイベントがあったら」→「このアクションをしてね」というイメージです。

functions.php に以下のような記述をします。

function my_preget_posts($query) {
  if (is_admin() || ! $query->is_main_query()){
    return;
  }
  if ($query->is_home()) {
     $query->set('posts_per_page', 3);
     return;
  }
  if ($query->is_category()) {
    $query->set('order', 'DESC');
    $query->set('orderby', 'date');
  }
}
add_action('pre_get_posts', 'my_preget_posts');

query_posts を使ってメインループを書き換えることもできますが、query_posts はデータを読み取った後に書き換えを行うため、効率が悪くページ表示速度への影響もあります。非推奨コードともされているので pre_get_posts を使いましょう。

カテゴリー : WordPress

タグ :

TOPへ