今回は、ワードプレス(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文の終了になります。
メインループの実用的なコード例
実際のテーマ開発では、以下のような形でメインループを使います。
<?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件です。

サブループ(WP_Query)の書き方と仕組み
サブループは、メインループとは別に、自分で条件を指定して投稿データを取得・表示する仕組みです。
例えば、
- 特定のカテゴリーだけ表示したい
- 最新3件だけ表示したい
- 特定のカスタム投稿タイプの記事を表示したい
- 固定ページに記事一覧を表示したい
といった場面で使います。
サブループで最もよく使われるのが 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件を表示するサンプルです。
$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件表示するサンプルです。
$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(); ?>
例③:現在の投稿を除外して関連記事を表示する
個別記事ページの下に、同じカテゴリーの関連記事を表示するサンプルです。
$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() を呼び出すことです。
ループ終了後に wp_reset_postdata() を実行しないと、メインループのデータが復元されず、以降の処理(サイドバーの表示やフッターの処理など)に不具合が発生する可能性があります。
サブループの後には必ず wp_reset_postdata() を書くと覚えてください。
メインループとサブループの使い分け
- archive.php でカテゴリーやタグの一覧を表示する
- index.php で投稿の新着一覧を表示する
- search.php で検索結果を表示する
- single.php で投稿の本文を表示する
- 固定ページに記事一覧を表示する
- 特定カテゴリーの記事だけ別枠で表示する
- サイドバーに人気記事や関連記事を表示する
- 1ページに複数の記事一覧を表示する
メインループはURLに応じて自動的にデータを取得済みなので、メインループで表示できるデータをわざわざサブループで再取得するのはクエリの無駄遣いです。
メインループで表示可能なデータはメインループで表示し、メインループでは対応できない場合にのみサブループを使うのが効率的なコードの書き方です。
get_posts()を使ったサブループ
WP_Queryの他に、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(); ?>
- 複雑な条件指定やページネーションに対応
- 投稿があるか(have_posts)の判定が組み込み
- 本格的なテーマ開発での使用が多い
- コードがシンプルで短い
- foreachで回すため直感的
- シンプルな一覧表示に向いている
ちなみに、どちらを使用するか迷ったらWP_Queryを使いましょう。
get_posts()でできることはWP_Queryでもすべてできます。
また、WP_Queryの方が対応範囲が広く、ページネーションにも対応しているため、汎用性が高いです。
query_posts()は使わない
古い記事やサンプルコードではquery_posts()を使ったサブループを見かけることがあります。
ですが、query_posts()関数は、現在は非推奨とされています。
使用すると、ページネーションの不具合やパフォーマンスの低下など、さまざまな問題を引き起こす原因にもなります。
query_posts()は絶対に使わず、WP_Queryまたは get_posts()を使用してください。
メインループの条件を変更したい場合(pre_get_posts)
- メインループの表示件数を変えたい
- 特定のカテゴリーを除外したい
など、メインループの取得条件を変更したい場合もあります。
その場合には、pre_get_postsというアクションフックを使います。
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’ );
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 で条件を指定してデータを取得するカスタムループです。
特定カテゴリーの記事表示や、固定ページへの記事一覧挿入に使います。
メインループで表示できるデータはメインループで、それ以外の条件が必要な場合にサブループを使うのが、効率的で正しい実装方法です。
当記事のコードを参考に、ぜひワードプレスのループ処理をマスターしてください。

コメント