こんにちは!コーダーのゆうしです。
WordPressで不動産サイトや採用サイトを制作していると「賃貸と売買」「正社員とアルバイト」のように複数のカスタム投稿タイプを1つの一覧ページにまとめて表示したいという場面がよくあります。この記事では pre_get_posts を使ってメインループで複数のカスタム投稿を混ぜて表示する方法を解説します。
なぜメインループを使うのか
複数の投稿タイプを混ぜて表示する場合、WP_Queryのサブループで実装する方法もありますが、サブループだとページネーションが正しく動作しないことがあります。pre_get_posts を使ってメインクエリを直接書き換えることで、ページネーションも含めて正常に動作させることができます。
実装コード
●functions.php
function pre_get_posts_custom( $query ) {
if ( is_admin() || !$query->is_main_query() ) { return; }
if ( $query->is_post_type_archive( 'post' ) && !$query->is_search() ) {
$query->set( 'post_type', array( 'rent', 'sell' ) );
}
}
add_action( 'pre_get_posts', 'pre_get_posts_custom' );functions.php に追加してください。'rent' や 'sell' の部分はご自身のカスタム投稿タイプのスラッグに変更してください。通常の投稿も混ぜたい場合は 'post' を配列に追加することで対応できます。
$query->set( 'post_type', array( 'rent', 'sell', 'post' ) );●archive.php/archive-○○.php
<?php if ( have_posts() ) : ?>
<?php while ( have_posts() ) : the_post(); ?>
<!-- ループの中身をここに記述 -->
<?php endwhile; ?>
<?php else : ?>
<p>まだ投稿がありません。</p>
<?php endif; ?>archive.phpのメインループはシンプルな形でOKです。クエリの書き換えはfunctions.php側で済んでいるので、テンプレート側は通常のループと同じ書き方になります。
コード解説
ポイントになるのは pre_get_posts の条件分岐です。
if ( is_admin() || !$query->is_main_query() ) { return; }この1行で管理画面とサブクエリへの影響を防いでいます。これがないと管理画面の投稿一覧など意図しない場所にも影響が出てしまうので必ず入れてください。
if ( $query->is_post_type_archive( 'post' ) && !$query->is_search() )is_post_type_archive('post') で対象のアーカイブページのみに絞り込み、!$query->is_search() で検索結果ページへの影響を除外しています。
躓きやすいポイント
ページネーションがおかしくなる
WP_Queryのサブループで実装しようとするとページネーションが正常に動作しないことがあります。この実装のようにメインクエリを pre_get_posts で書き換える方法を使ってください。
管理画面の投稿一覧に影響が出る
is_admin() の条件分岐が抜けていると管理画面にも影響が出ます。必ず最初の行に記述してください。
カスタム投稿が表示されない
カスタム投稿タイプの登録時に has_archive が true になっているか確認してください。false の場合はアーカイブページ自体が存在しないため表示されません。
register_post_type( 'rent', array(
'has_archive' => true, // これがtrueになっているか確認
// 他の設定...
));まとめ
pre_get_posts を使ってメインクエリを書き換えることで、複数のカスタム投稿タイプを1つのアーカイブページに混ぜて表示できます。サブループと違いページネーションも正常に動作するのが大きなメリットです。不動産・採用・ポートフォリオなど複数の投稿タイプを扱うサイトでぜひ活用してみてください。
ご不明な点やコーディングのご依頼はお問い合わせからお気軽にどうぞ。

