WordPressメインループの基本的な書き方と使い方

WordPressのループは「メインループ」と「サブループ」と呼ばれるものがあります。ここではメインループの基本の書き方やコードの意味、表示させたい条件に応じた使い方を紹介していきます。

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

メインループの基本のコードは以下の形です。

PHP
<?php if(have_posts()): ?>
  <!-- もし投稿があった場合に何かをしたいときはココ -->
  <?php while(have_posts()): the_post(); ?>
    <!-- 投稿内容を繰り返し処理・表示 -->
  <?php endwhile; ?>
  <!-- 投稿内容のループ処理が終わった後に何かをしたいときはココ -->
<?php else: ?>
  <!-- 投稿がなかった時にしたいこと -->
<?php endif; ?>

投稿データがあるか、あれば取り出し、取り出せるデータがなくなったらループが終了となります。

次からそれぞれのコードについて詳しくみていきます。

have_posts()

have_posts() はクエリによって取得したデータに、ループさせる投稿があるかどうかをチェックします。

have_posts() の返り値は真偽値。

if(have_posts()) は「投稿データがあれば」という条件分岐、while(have_posts()) は「投稿データがあるだけ処理を繰り返す」コードです。

the_post()

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

この関数は、$wp_query にある記事データを1件取り出して $post へ格納し、参照している $wp_query のデータ一覧から1件削除する、という処理をしています。

while文で繰り返すことで次々と記事を取り出し、取り出したものは削除されていきます。取り出すものがなくなったら処理も終了です。

endwhile、endif

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

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

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

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

【メモ】

確実に投稿がある状態なら、while文のみでもOK。

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

投稿の繰り返しが必要なく、投稿があるかないかの判別のみ、メインクエリの一つ目の投稿だけを取得できれば良いといった場合はif文だけでもOK。

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

single.pnpやpage.phpで表示される記事の詳細ページは、該当する投稿が1件のみであり投稿がない場合は404ページを表示すれば良いので、if文やwhile文を書かなくても問題ないと思います。もちろん作法に従った方エラーの可能性は少ないと思いますが、私はあまり問題になったことがないので、これらのテンプレートファイルには書かないことがほとんどです。

ループのコード例

投稿タイトルのリスト表示

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

  • もし投稿があれば、h2タグの内容を表示。
  • リンク付きの投稿タイトルを繰り返し表示。
  • 投稿がなければ、「記事はありません」と表示。
PHP
<?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>
<?php endif; ?>

ループの中では <?php the_〇〇() ?> といった投稿情報を簡単に表示させるテンプレートタグが使用できます。
代表的な出力テンプレートタグに以下のものがあります。

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

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

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

最初だけ変える

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

PHP
<?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
<?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 はデータベースを検索する前に実行されるアクションフックです。

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

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

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

index