WordPress メインループとサブループの表示方法

WordPress メインループとサブループの表示方法

WordPress で投稿を表示するためのメインループとサブループの表示方法を紹介します。
例えば、最新記事一覧やカテゴリー別記事一覧を表示したい時に便利な方法です。

ループは大きく分けて「メインループ」と「サブループ」の2つに分けられます。
この記事では使用頻度の高いサブループの表示方法をメインに紹介していきます。

  1. メインループの表示方法
  2. サブループの表示方法
    1. 投稿の表示件数を指定する方法
    2. 投稿をターム別に絞り込む方法
    3. 特定の投稿を除外する方法
    4. 現在表示している投稿を除外する方法
    5. 投稿を昇順・降順などで指定する方法
    6. 関連記事の表示、表示中の投稿と同じタームに分類されている投稿をランダムに表示する方法
    7. 投稿数を取得する方法
    8. カスタムフィールドの値で投稿をソートする方法
    9. 投稿タイプを複数指定する方法
    10. 投稿一覧に年の見出しを付ける方法
    11. 投稿を順序順で表示する方法
    12. 非公開記事を除外する方法
  3. 固定ページの内容をトップページに表示させる方法
  4. 投稿が表示されない時の注意点

メインループの表示方法

投稿を表示するためのループのことをメインループと呼びます。
投稿や固定ページのテンプレートファイル内で使用することで、ページタイトルや本文の内容を表示することができます。
例えば、投稿の内容を表示したい場合は、次のコードをテンプレートファイルに追加します。

<?php if (have_posts()): ?>
<?php while (have_posts()) : the_post(); ?>
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php echo get_the_date(); ?>
<?php the_permalink(); ?>
<?php echo get_the_title(); ?>
<?php the_content(); ?>
</div>
<?php endwhile; ?>
<?php else: ?>
<!-- 投稿が無い場合の処理 -->
<?php endif; ?>

ページタイトルや本文の内容を表示したい場合は、while 以降に タイトルを表示する get_the_title() や、本文の内容を表示する the_content() を使うことで投稿内容を表示します。
投稿内容が必ずある場合は、次のようにif文を省略することもできます。

<?php while (have_posts()): the_post(); ?>
<!-- 中略 -->
<?php endwhile; ?>

メインループで使用する $wp_query は一度しか呼び出すことができません。そのため、複数のループを表示するためには、rewind_posts() を呼び出してクエリーを再利用するか、新しいクエリーオブジェクトを生成する必要があります。

クエリーとは記事を表示するためのリクエストの塊と考えるとイメージしやすいと思います。
例えば、最新の記事を5件表示したい場合に、その希望をリクエストとしてまとめてシステムに渡すと、その内容に沿った記事情報を持ってきてくれるような感じです。初心者の方には難しいかもしれませんが、これが理解できると WordPress の表示に苦手意識はなくなるでしょう。

話を戻して、基本的には一つのテンプレート内で使用メインループは一つまで、と覚えておきましょう。
ただ、ループを複数設置したいってことはよくあります。
メインループとは別にループを複数設置したい場合は、次に紹介するサブループを使います。

サブループの表示方法

サブループは、メインループとは別にループを作りたい時に使用します。
例えば、カスタム投稿タイプ Products の投稿を表示する場合は、次のコードをテンプレートファイルに追加します。

<?php
$args = array( 'post_type' => 'Products' ); // カスタム投稿タイプ Products
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<?php while ($the_query->have_posts()): $the_query->the_post(); ?>
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php echo get_the_date(); ?>
<?php the_permalink(); ?>
<?php echo get_the_title(); ?>
<?php the_content(); ?>
</div>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>
<?php else: ?>
<!-- 投稿が無い場合の処理 -->
<?php endif; ?>

サブループはメインループと違いループ終わりにクエリをリセットする必要があります。サブループでは必ず endwhile のループ終わりにページ送り関数 wp_reset_postdata を追加して、ループをリセットして直前のクエリーを復元します。

そもそも、メインループ(メインクエリ)とサブループ(二番目のクエリ)は次のように違いがあります。
メインループは、URL によるリクエストに基づいたクエリが、テンプレートが読み込まれる前に実行されるのに対して、サブループはテーマのテンプレートやプラグインのファイルの中で実行されます。そのため、サブループの実行後はサブループがクエリーを上書きしてしまうため、メインクエリを復元する必要があります。

投稿の表示件数を指定する方法

サブループの表示件数を制御する場合は posts_per_page を追加します。
例えば、投稿を5件だけ表示したい場合はパラメーター 'posts_per_page' => 5 を追加します。

<?php
$args = array(
'post_type' => 'Products', // 投稿タイプのスラッグを指定
'posts_per_page' => 5 // 投稿件数の指定
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

非公開の投稿を除外したい場合は「非公開記事を除外する方法」をご確認ください。
記事の表示件数を全件表示にしたい場合は、パラメーター 'posts_per_page' => -1 で、値を-1(全件表示)と指定します。
表示件数の制御を、管理画面や function.php で行なっている場合でも、テンプレートに直接指定されている表示件数が優先されます。

投稿をターム別に絞り込む方法

サブループの投稿をカスタム分類(タクソノミー) Products-cat のターム item1 別に絞り込む場合は tax_query を追加します。

<?php
$args = array(
'post_type' => 'Products', // 投稿タイプのスラッグを指定
'tax_query' => array(
array(
'taxonomy' => 'Products-cat', // タクソノミースラッグを指定
'field' => 'slug',
'terms' => 'item1', // タームスラッグを指定
)
)
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

スラッグを複数指定する場合は array を追加います。
複数選択を条件に絞り込む場合の方法は続いて紹介します。

'terms' => array('item1','item2') // タームスラッグを複数指定

特定のタームを除外する場合は、パラメーター 'operator' => 'NOT IN' を追加します。

<?php
$args = array(
'post_type' => 'Products', // 投稿タイプのスラッグを指定
'tax_query' => array(
array(
'taxonomy' => 'Products-cat', // タクソノミースラッグを指定
'field' => 'slug',
'terms' => 'item1', // タームスラッグを指定
'operator' => 'NOT IN' // 指定したタームを除外する
)
)
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

指定したタームを複数選択している条件で絞り込む場合は tax_query のタームの指定を複数指定します。
例えば、タームスラッグ item1 と item2 を選択している投稿を絞り込む場合は tax_query の指定を次のようにします。

'tax_query' => array(
array(
'taxonomy' => ' Products-cat', // タクソノミースラッグを指定
'field' => 'slug',
'terms' => 'item1' // タームスラッグを指定
),
array(
'taxonomy' => ' Products-cat', // タクソノミースラッグを指定
'field' => 'slug',
'terms' => 'item2' // タームスラッグを指定
)
)

カンマの記入漏れでエラーが起こりやすいの注意してください。

特定の投稿を除外する方法

サブループで特定の投稿を除外する場合は、パラメーター post__not_in を追加します。
例えば、投稿ID 11,22,33,44,55 を除外する場合は次のように指定します。

<?php
$args = array(
'post_type' => 'Products', // 投稿タイプのスラッグを指定
'post__not_in' => array( 11,22,33,44,55 )
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

現在表示している投稿を除外する方法

現在表示しているページを除外する場合は、パラメーター post__not_in$post->ID を指定します。

<?php
$args = array(
'post_type' => 'Products', // 投稿タイプのスラッグを指定
'post__not_in' => array($post->ID)
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

投稿を昇順・降順などで指定する方法

サブループの投稿を昇順(最低から最高へ)で並び変える場合は、パラメーター 'order' => 'ASC' を追加します。

<?php
$args = array(
'post_type' => 'Products', // 投稿タイプのスラッグを指定
'order' => 'ASC'
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

サブループの投稿を降順(最高から最低へ)で並び変える場合は、パラメーター 'order' => 'DESC' に変更します。

関連記事の表示、表示中の投稿と同じタームに分類されている投稿をランダムに表示する方法

現在表示している投稿を除外して、同じタームに分類された投稿をランダムに表示する場合は get_the_terms を使用します。
この方法はタームを複数選択している場合には対応していません。
タームを複数選択している場合は WordPress 現在表示されている投稿と同じタームに分類された投稿を表示する方法をご覧ください。

<?php
$terms = get_the_terms($post->ID,'products-cat');
foreach( $terms as $term ) {
$term_slug = $term->slug; // 現在表示している投稿に属しているタームを取得
}
$args = array(
'post_type' => 'Products', // カスタム投稿タイプ Products
'post__not_in' => array($post->ID), // 現在表示している投稿を除外
'posts_per_page' => 9, // 表示件数9件
'orderby' => 'rand', // ランダム
'tax_query' => array( // タクソノミーの指定
'taxonomy' => 'products-cat',
'field' => 'slug',
'terms' => $term_slug, // 取得したタームを指定
)
); $the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

WordPress のプラグイン Anything Order など、並び順変更プラグインを使用して投稿の並べ替えを行うと、プラグインのバージョンによっては、クエリとテンプレートの記述がぶつかって表示がランダムにならない場合があります。その場合は、プラグインのアップデートやプラグインの停止などで対処しましょう。

投稿数を取得する方法

サブループで指定したクエリから投稿数を取得する場合は、 $the_query->found_posts を使って取得します。

<?php echo $the_query->found_posts; ?>

カスタムフィールドの値で投稿をソートする方法

カスタムフィールドの値で投稿をソートする場合は meta_query を使用します。
例えば、カスタム投稿タイプ Products のカスタムフィールド ホゲホゲ に、フガフガ が入力されている場合の投稿を表示するには、次のコードをテンプレートファイルに追加します。

<?php // カスタムフィールドの値で投稿をソートする
$args = array(
'post_type' => 'Products', // 投稿タイプを指定
'posts_per_page' => 5, // 投稿の表示件数を指定
'meta_query' => array( // カスタムフィールドを指定
array(
'key' => 'ホゲホゲ', // フィールド名の指定
'value' => 'フガフガ', // 値の指定
'compare' => 'LIKE' // フィールド値の部分一致
)
)
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

ソートの詳しい情報はWordPress 投稿をカスタムフィールドの値でソートして一覧を取得する方法をご覧ください。

リピーターフィールドの値でソートする場合は「WordPress で投稿一覧をカスタムフィールドの値でソートする方法」の「リピーターフィールド値でソートする方法」をご覧ください。

投稿タイプを複数指定する方法

サブループで投稿タイプを複数指定する場合は post_typearray を使用して、ポストタイプのスラッグを複数指定します。
例えば、カスタム投稿タイプのスラッグ information と Products の二つを混ぜて、そこから最新の投稿を5件表示する場合は、次のコードをテンプレートファイルに追加します。

<?php
$args = array(
'post_type' => array('information','Products'), // 投稿タイプを複数指定
'posts_per_page' => 5 // 投稿件数を指定
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

投稿一覧に年の見出しを付ける方法

投稿一覧に年の見出しを付ける方法を紹介します。
例えば、投稿タイプのスラッグが news の場合、投稿一覧に年毎の見出しを表示するには、次のコードを追加します。

<?php
$post_year = false; // 年の比較用変数の初期化
// サブループの準備
$args = array(
'post_type' => 'news', // 投稿タイプのスラッグを指定
'post_status' => 'publish', // 公開済の投稿を指定
'posts_per_page' => -1, // 投稿件数の指定
'order' => 'DESC', // 降順でソート
'orderby'=>'date' // 日付で並べる
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<?php while ($the_query->have_posts()): $the_query->the_post(); ?>
<?php // 年を表示、続く投稿が同一年なら表示をスルー
if ( $post_year != get_post_time('Y') ) { // 比較の値と投稿年が異なる場合に年を表示
echo '<h2>'.get_post_time('Y年').'</h2>'; //投稿の年を表示
}
?>
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php echo get_the_date(); ?>
<?php the_permalink(); ?>
<?php echo get_the_title(); ?>
<?php the_content(); ?>
</div>
<?php
$post_year = get_post_time('Y'); // 年月の比較用の変数に今の投稿の年月を代入
endwhile;
?>
<?php wp_reset_postdata(); ?>
<?php else: ?>
<!-- 投稿が無い場合の処理 -->
<?php endif; ?>

表示に月も混ぜたい時は投稿一覧に年と月の見出しを付ける方法をご覧ください。

投稿を順序順で表示する方法

投稿を順序順で表示する方法を紹介します。
例えば、投稿タイプのスラッグが news の場合、投稿を順序順で表示するには、次のコードを追加します。

<?php
$post_year = false; // 年の比較用変数の初期化
// サブループの準備
$args = array(
'post_type' => 'news', // 投稿タイプのスラッグを指定
'post_status' => 'publish', // 公開済の投稿を指定
'posts_per_page' => -1, // 投稿件数の指定
'orderby' => 'menu_order', // 順序順で表示
'order' => 'ASC' // 昇順
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

非公開記事を除外する方法

非公開の投稿を除外したい場合は 'post_status' の値を publish を指定します。

<?php
$args = array(
'post_type' => 'Products', // 投稿タイプのスラッグを指定
'post_status' => 'publish', // 公開済の投稿を指定
'posts_per_page' => 5 // 投稿件数の指定
);
$the_query = new WP_Query($args); if($the_query->have_posts()):
?>
<!-- 以下省略 -->

ログイン中のクライアントから「非公開記事が表示されてるよ!」と言われることが多々あります…。
publish を指定することで、公開済みの投稿のみを表示となり、非公開記事が表示されなくなります。

固定ページの内容をトップページに表示させる方法

トップページに固定ページを表示したい時はクエリの post_type の指定を page_id に変更します。
例えば、固定ページのページIDが 123 の場合、トップページにページID123のページを表示したい時は、次のコードをテンプレートファイルに追加します。

<?php $args = array( 'page_id' => 123 ); $the_query = new WP_Query($args); if($the_query->have_posts()): ?>
<!-- 以下省略 -->

固定ページのIDは管理画面の固定ページの編集画面のURLから参照することができます。
また、ID指定をページスラッグに変更したい時は page_idpagename に変更して対応します。

<?php$args = array( 'pagename' => 'products' ); $the_query = new WP_Query($args); if($the_query->have_posts()): ?>
<!-- 以下省略 -->

投稿が表示されない時の注意点

投稿が正しく表示されない時やエラーが表示される時は、if文の記載内容や、各種パラメーターの区切りが正しくない時によく起こります。
構造の再確認と合わせて、パラメーターを区切る「,(カンマ)」の入れ忘れに注意しましょう。
逆に、パラメーターの終わりに「,(カンマ)」を「つける or つけない」など、癖があるので気をつけましょう。

まとめ

WordPress で投稿を表示するためのメインループとサブループの表示方法を紹介しました。
サブループの表示になれると「新着記事一覧」や「カテゴリーに紐づく記事一覧」など、巷でよく見る記事一覧ページが簡単に出力できるようになります。なれるまでは難しいですが、試行錯誤してチャレンジしてみましょう!