ワードプレスのメインループとサブループの違いを理解して記事を表示する

ワードプレスのメインループとサブループの違いを理解して記事を表示する ワードプレス

今回は、ワードプレス(WordPress)のメインループとサブループの違いを理解して記事を表示する方法を紹介します。

ワードプレスで記事一覧を表示するために使うのが「ループ」という仕組みです。
ループには「メインループ」と「サブループ」の2種類があり、状況に応じて使い分ける必要があります。

この使い分けを理解していないと、思い通りに記事が表示されなかったり、Webサイトの表示速度が遅くなる原因にもなります。

当記事では、定番のメインループのコードの意味から、WP_Queryを使ったサブループの書き方、そして両者の使い分けまで、初心者の方にもわかるように解説します。
ぜひ参考にしてください。

ワードプレスの「ループ」とは

ワードプレスにおける「ループ」とは、データベースから取得した投稿データを繰り返し処理して画面に表示する仕組みのことです。

例えば、ブログのトップページに新着記事が5件並んでいるのを見たことがあると思います。
あの表示を実現しているのがループです。

【ループの基本的な流れ】
1. データベースから投稿データを取得する(クエリ)
2. 取得したデータがあるかチェックする
3. データがある分だけ繰り返し表示する
4. すべて表示し終えたら終了する

この「繰り返し処理」が「ループ(Loop)」と呼ばれる理由です。

ループにはメインループサブループの2種類があります。
まずは、それぞれの特徴と違いを確認しましょう。

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

メインループ
  • URLに応じてワードプレスが自動的に投稿データを取得してくれる
  • テンプレートファイルに応じた情報が表示される
  • 取得条件の細かい指定はできない(件数は管理画面で設定可)
  • 1ページにつき1つだけ使える
サブループ
  • 自分で取得条件を指定してデータを取得する
  • カテゴリー、件数、並び順など細かい条件指定が可能
  • 1ページに複数設置できる
  • 使用後はwp_reset_postdata()でリセットが必要
メインループは、「ワードプレスが自動で持ってきてくれるデータを表示する仕組み」になります。
それに対して、サブループは「自分で条件を指定してデータを取りに行く仕組み」と理解しておきましょう。

メインループの書き方と仕組み

メインループは、ワードプレスのテーマ開発で最も基本となるコードです。
archive.php(一覧ページ)やindex.php(トップページ)などのテンプレートファイルで使用します。

メインループの基本コード

■ メインループの基本形

<?php if ( have_posts() ) : ?>
  <?php while ( have_posts() ) : the_post(); ?>

    <!– ここに繰り返し表示したい内容を記述 –>

  <?php endwhile; ?>
<?php else : ?>
  <p>投稿が見つかりませんでした。</p>
<?php endif; ?>

コードの意味を1行ずつ理解する

この定番コードを、1行ずつ分解して解説します。

①、if ( have_posts() ) :

このif文では、「表示する投稿記事があるかどうか」をチェックしています。
投稿がある場合は「true」を返し、以降の処理に進みます。投稿がなければ「else」に進みます。

②、while ( have_posts() ) : the_post();

「投稿がある間、繰り返し処理を実行する」という命令です。
the_post() は、次の投稿データを取り出してグローバル変数$postにセットする関数です。
ループが1周するごとに、次の投稿データに切り替わります。

③、繰り返し表示する内容

ループの中には、タイトルや日付、本文などの表示コードを記述します。
ここに書いた内容が、投稿の数だけ繰り返し出力されます。

④、endwhile; / else: / endif;

「endwhile」でループ終了し、「else」には投稿がなかった場合の処理を記述します。
さらに、「endif」でif文の終了になります。

メインループの実用的なコード例

実際のテーマ開発では、以下のような形でメインループを使います。

■ 記事一覧を表示するメインループ(archive.php用)

<?php if ( have_posts() ) : ?>
  <div class=”article-list”>
  <?php while ( have_posts() ) : the_post(); ?>
    <article class=”post-item”>
      <time><?php echo get_the_date( ‘Y.m.d’ ); ?></time>
      <h2><a href=”<?php the_permalink(); ?>”><?php the_title(); ?></a></h2>
      <?php if ( has_post_thumbnail() ) : ?>
        <?php the_post_thumbnail( ‘medium’ ); ?>
      <?php endif; ?>
      <p><?php echo get_the_excerpt(); ?></p>
    </article>
  <?php endwhile; ?>
  </div>
<?php else : ?>
  <p>まだ記事がありません。</p>
<?php endif; ?>

ちなみに、メインループの表示件数は、管理画面の「設定」→「表示設定」にある「1ページに表示する最大投稿数」で変更できます。
デフォルトは10件です。
1ページに表示する最大投稿数

サブループ(WP_Query)の書き方と仕組み

サブループは、メインループとは別に、自分で条件を指定して投稿データを取得・表示する仕組みです。

例えば、

  • 特定のカテゴリーだけ表示したい
  • 最新3件だけ表示したい
  • 特定のカスタム投稿タイプの記事を表示したい
  • 固定ページに記事一覧を表示したい

といった場面で使います。

サブループで最もよく使われるのが WP_Query クラスです。

WP_Queryの基本コード

■ サブループの基本形(WP_Query)

<?php
$args = array(
  // ここに取得条件を記述
);
$the_query = new WP_Query( $args );
?>

<?php if ( $the_query->have_posts() ) : ?>
  <?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>

    <!– ここに繰り返し表示したい内容を記述 –>

  <?php endwhile; ?>
<?php else : ?>
  <p>投稿が見つかりませんでした。</p>
<?php endif; ?>
<?php wp_reset_postdata(); ?>

メインループとの違いは以下の3つです。

メインループとの違い
  • $argsに取得条件(投稿タイプ、カテゴリー、件数など)を配列で指定する
  • have_posts()やthe_post()の前に$the_query->を付ける(メインループのグローバル変数と区別するため)
  • ループ終了後にwp_reset_postdata()でデータをリセットする

よく使うパラメータ($args)一覧

WP_Queryの$argsに指定できる主なパラメータをまとめました。

  • ‘post_type’ => ‘post’:投稿タイプの指定(’post’=投稿、’page’=固定ページ、カスタム投稿タイプ名も可)
  • ‘posts_per_page’ => 5:表示件数(-1 で全件表示)
  • ‘category_name’ => ‘news’:カテゴリーのスラッグで絞り込み
  • ‘cat’ => 3:カテゴリーIDで絞り込み
  • ‘tag’ => ‘pickup’:タグのスラッグで絞り込み
  • ‘orderby’ => ‘date’:並び順の基準(’date’=公開日、’modified’=更新日、’rand’=ランダム、’title’=タイトル順)
  • ‘order’ => ‘DESC’:並び順(’DESC’=降順/新しい順、’ASC’=昇順/古い順)
  • ‘post_status’ => ‘publish’:公開済みの投稿のみ取得
  • ‘post__not_in’ => array( 123, 456 ):特定の投稿IDを除外
  • ‘paged’ => $paged:ページネーション対応

サブループの実用的なコード例

例①:特定のカテゴリーの最新記事を3件表示する

固定ページのトップに「お知らせ」カテゴリーの最新3件を表示するサンプルです。

<?php
$args = array(
  ‘post_type’ => ‘post’,
  ‘category_name’ => ‘news’,
  ‘posts_per_page’ => 3,
  ‘orderby’ => ‘date’,
  ‘order’ => ‘DESC’,
);
$news_query = new WP_Query( $args );
?>

<?php if ( $news_query->have_posts() ) : ?>
  <h2>お知らせ</h2>
  <ul>
  <?php while ( $news_query->have_posts() ) : $news_query->the_post(); ?>
    <li>
      <time><?php echo get_the_date( ‘Y.m.d’ ); ?></time>
      <a href=”<?php the_permalink(); ?>”><?php the_title(); ?></a>
    </li>
  <?php endwhile; ?>
  </ul>
<?php endif; ?>
<?php wp_reset_postdata(); ?>

お知らせカテゴリーの記事一覧

例②:カスタム投稿タイプの記事を5件表示する

制作実績(works)というカスタム投稿タイプの記事を5件表示するサンプルです。

<?php
$args = array(
  ‘post_type’ => ‘works’,
  ‘posts_per_page’ => 5,
  ‘post_status’ => ‘publish’,
);
$works_query = new WP_Query( $args );
?>

<?php if ( $works_query->have_posts() ) : ?>
  <h2>制作実績</h2>
  <div class=”works-list”>
  <?php while ( $works_query->have_posts() ) : $works_query->the_post(); ?>
    <article>
      <?php if ( has_post_thumbnail() ) : ?>
        <a href=”<?php the_permalink(); ?>”><?php the_post_thumbnail( ‘medium’ ); ?></a>
      <?php endif; ?>
      <h3><a href=”<?php the_permalink(); ?>”><?php the_title(); ?></a></h3>
    </article>
  <?php endwhile; ?>
  </div>
<?php endif; ?>
<?php wp_reset_postdata(); ?>

例③:現在の投稿を除外して関連記事を表示する

個別記事ページの下に、同じカテゴリーの関連記事を表示するサンプルです。

<?php
$categories = get_the_category();
if ( $categories ) :
  $args = array(
    ‘post_type’ => ‘post’,
    ‘cat’ => $categories[0]->term_id,
    ‘posts_per_page’ => 4,
    ‘post__not_in’ => array( get_the_ID() ),
  );
  $related_query = new WP_Query( $args );
?>
  <?php if ( $related_query->have_posts() ) : ?>
    <h2>関連記事</h2>
    <?php while ( $related_query->have_posts() ) : $related_query->the_post(); ?>
      <a href=”<?php the_permalink(); ?>”><?php the_title(); ?></a>
    <?php endwhile; ?>
  <?php endif; ?>
  <?php wp_reset_postdata(); ?>
<?php endif; ?>

こちらのサンプルでは、「‘post__not_in’ => array( get_the_ID() )」で現在表示中の投稿を除外しています。
このコード入れておかないと、現在表示中の記事も関連記事として表示されてしまいます。

wp_reset_postdata()を忘れずに

サブループを使う際に最も重要なルールが、ループ終了後に wp_reset_postdata() を呼び出すことです。

サブループでは、the_post() によってグローバル変数 $post がサブループの投稿データで上書きされます。
ループ終了後に wp_reset_postdata() を実行しないと、メインループのデータが復元されず、以降の処理(サイドバーの表示やフッターの処理など)に不具合が発生する可能性があります。

サブループの後には必ず wp_reset_postdata() を書くと覚えてください。

メインループとサブループの使い分け

メインループを使う場面
  • archive.php でカテゴリーやタグの一覧を表示する
  • index.php で投稿の新着一覧を表示する
  • search.php で検索結果を表示する
  • single.php で投稿の本文を表示する
サブループを使う場面
  • 固定ページに記事一覧を表示する
  • 特定カテゴリーの記事だけ別枠で表示する
  • サイドバーに人気記事や関連記事を表示する
  • 1ページに複数の記事一覧を表示する
【注意点:パフォーマンスについて】
メインループはURLに応じて自動的にデータを取得済みなので、メインループで表示できるデータをわざわざサブループで再取得するのはクエリの無駄遣いです。
メインループで表示可能なデータはメインループで表示し、メインループでは対応できない場合にのみサブループを使うのが効率的なコードの書き方です。

get_posts()を使ったサブループ

WP_Queryの他に、get_posts()関数を使ったサブループの書き方もあります。
シンプルな記事一覧を取得したい場合に便利なので、合わせて覚えておきましょう。

■ get_posts() を使ったサブループ

<?php
$args = array(
  ‘post_type’ => ‘post’,
  ‘category_name’ => ‘news’,
  ‘posts_per_page’ => 3,
);
$posts_array = get_posts( $args );
?>

<?php foreach ( $posts_array as $post ) : setup_postdata( $post ); ?>
  <a href=”<?php the_permalink(); ?>”><?php the_title(); ?></a>
<?php endforeach; ?>
<?php wp_reset_postdata(); ?>

WP_Queryの特徴
  • 複雑な条件指定やページネーションに対応
  • 投稿があるか(have_posts)の判定が組み込み
  • 本格的なテーマ開発での使用が多い
get_posts()の特徴
  • コードがシンプルで短い
  • foreachで回すため直感的
  • シンプルな一覧表示に向いている

ちなみに、どちらを使用するか迷ったらWP_Queryを使いましょう。

get_posts()でできることはWP_Queryでもすべてできます。
また、WP_Queryの方が対応範囲が広く、ページネーションにも対応しているため、汎用性が高いです。

query_posts()は使わない

古い記事やサンプルコードではquery_posts()を使ったサブループを見かけることがあります。
ですが、query_posts()関数は、現在は非推奨とされています。

query_posts()関数は、メインクエリ自体を上書きしてしまいます。
使用すると、ページネーションの不具合やパフォーマンスの低下など、さまざまな問題を引き起こす原因にもなります。

query_posts()は絶対に使わず、WP_Queryまたは get_posts()を使用してください。

メインループの条件を変更したい場合(pre_get_posts)

  • メインループの表示件数を変えたい
  • 特定のカテゴリーを除外したい

など、メインループの取得条件を変更したい場合もあります。
その場合には、pre_get_postsというアクションフックを使います。

■ functions.php に記述:トップページの表示件数を5件にする

function my_change_main_query( $query ) {
  if ( ! is_admin() && $query->is_main_query() ) {
    if ( $query->is_home() ) {
      $query->set( ‘posts_per_page’, 5 );
    }
  }
}
add_action( ‘pre_get_posts’, ‘my_change_main_query’ );

■ functions.php に記述:特定カテゴリーをメインループから除外する

function my_exclude_category( $query ) {
  if ( ! is_admin() && $query->is_main_query() ) {
    if ( $query->is_home() ) {
      $query->set( ‘category__not_in’, array( 5 ) );
    }
  }
}
add_action( ‘pre_get_posts’, ‘my_exclude_category’ );

pre_get_posts を使うときは、「! is_admin()(管理画面では実行しない)」と「$query->is_main_query()(メインクエリのみ対象)」の2つの条件を必ず付けてください。
これを忘れると、管理画面の投稿一覧やサブループにまで影響が出てしまいます。

最後に

今回は、ワードプレスのメインループとサブループの違いを理解して記事を表示する方法を紹介しました。

メインループは、ワードプレスが自動的にデータを取得して表示する基本のループです。
archive.php や index.php での記事一覧表示に使います。

サブループは、WP_Query で条件を指定してデータを取得するカスタムループです。
特定カテゴリーの記事表示や、固定ページへの記事一覧挿入に使います。

メインループで表示できるデータはメインループで、それ以外の条件が必要な場合にサブループを使うのが、効率的で正しい実装方法です。

当記事のコードを参考に、ぜひワードプレスのループ処理をマスターしてください。

コメント

タイトルとURLをコピーしました