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

更新2022/01/11

ループはWordPressで投稿を表示させるための仕組みのことを指し、記事一覧や詳細ページなどで使われています。

WordPressを使う上で覚えておくべきシステムと言えます。

まずループとクエリは理解しておくべきところなのでその説明から記述していきます。

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

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

ループは言葉の通り繰り返すものを指しています。この繰り返すものというのは投稿です。

アーカイブ・カテゴリーページの一覧やサイドバーに表示される新着記事、人気記事や関連記事の一覧など、投稿一覧を表示させるための仕組みをWordPressではループと呼んでいます。

ループの仕組みが分かるとカスタマイズの幅が広がるので、しっかり理解しておきたいものです。

クエリとは

ループについて調べると、セットで「クエリ」という言葉を使われていることが多いです。
このクエリとはデータベースに問い合わせ(処理要求)することを言います。

投稿した情報はデータベースに保存されています。投稿記事を表示させるには、データベースから表示させたい記事を指定しなければなりません。
この時に「表示させたい記事の条件」をクエリと言います。

WordPressはアクセスしたURLによって自動的に投稿データを取得します。

URLによって自動的に条件を決めている内容を「メインクエリ」、それ以外にこちらから指定する条件を「サブクエリ」と言います。

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

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

「?」以降にある内容が記事を取得するための条件になっています。これがクエリです。
上記の形だと「IDが1234の記事」を条件にしています。

この形のURLを「https://komaricote.com/post_name/」というようなユーザーが見やすい形にカスタムしているのです。

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

ループには「メインループ」と「サブループ」があります。
メインクエリを使ったループを「メインループ」、サブクエリを使ったループを「サブループ」と言います。

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

ループはこのように使い分けていきます。

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

サブループも似ているコード内容になりますが、表示させる投稿を新たに指定する必要があります。サブループの使い方は以下をご覧ください。

【サブループの使い方→】サブループで任意の投稿一覧を表示

ベーシックなループの形

メインクエリで表示できる投稿を表示させるときはこのベーシックな形で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 までの内容がある限り、繰り返し処理をしていきます。

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

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

the_post()

the_post() は投稿を表示するためのコード。while(have_posts()) とは必ずセットです。

投稿内容を表示させなくていいなら the_post() はいらないけど、while(have_posts()) を使ってそういったことはほぼないと思います。

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

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

endwhile、endif

endwhile・endifは、if文(もし〜)の処理や、while文(繰り返し処理)が終わることを明示するもの。

if(have_posts()):while(have_posts()): のようにコロンをつけている場合は必須。ないとエラーになるので、もしエラーになったらここをチェックします。
波括弧「{}」を使っている場合は記述しません。

// endif, endwhile はいらない
if(have_posts()) {
  //  投稿があったらすること
  while(have_posts()) {
    // 投稿の繰り返しですること
  }
}

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

この例の場合、以下の内容を行います。
もし投稿があれば、h2の部分を表示。その後に投稿タイトルを繰り返し表示させる。
投稿がなければ、「記事はありません」と表示させる。

// メインループ(single.php, category, archive)
<?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; ?>

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

ワードプレスの投稿表示には $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');

pre_get_posts の詳細は以下の記事にまとめていますので、ご確認ください。

【関連記事】メインクエリを操作して投稿を表示させる pre_get_posts

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

【関連記事】query_postsはNG!非推奨コードは使わない

カテゴリー : WordPress

TOPへ