2026年5月20日
2026年5月20日
WordPressのループをカスタマイズする方法
はじめに
WordPressの「ループ(The Loop)」は投稿を繰り返し表示する仕組みです。メインループは have_posts() と the_post() で動作しますが、WP_Query を使えば任意の条件で独自のサブループを作れます。
症状・原因
- 特定カテゴリの投稿だけ一覧表示したい
- 同ページに複数の投稿リストを表示したい
- ループ内のレイアウトをカード型にしたい
- サブループでページネーションが効かない
解決手順
ステップ1:メインループの基本
// index.php・archive.php
<?php if (have_posts()) : ?>
<div class="post-grid">
<?php while (have_posts()) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class('card'); ?>>
<?php if (has_post_thumbnail()) : ?>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
<?php endif; ?>
<div class="card-body">
<h2 class="card-title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h2>
<p class="card-excerpt"><?php the_excerpt(); ?></p>
<time datetime="<?php echo get_the_date('c'); ?>">
<?php echo get_the_date(); ?>
</time>
</div>
</article>
<?php endwhile; ?>
</div>
<?php the_posts_pagination(); ?>
<?php else : ?>
<p>投稿が見つかりません。</p>
<?php endif; ?>
ステップ2:WP_Queryでカスタムループを作る
// サイドバーや任意の場所に新着投稿を表示
$recent_query = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 5,
'orderby' => 'date',
'order' => 'DESC',
'no_found_rows' => true, // ページネーション不要なら高速化
]);
if ($recent_query->have_posts()) :
echo '<ul class="recent-posts">';
while ($recent_query->have_posts()) : $recent_query->the_post(); ?>
<li>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
<time><?php echo get_the_date(); ?></time>
</li>
<?php endwhile;
echo '</ul>';
endif;
// 必須: サブループ後はメインクエリをリセット
wp_reset_postdata();
ステップ3:カテゴリ・タグ・カスタムフィールドで絞り込む
// カテゴリスラッグで絞り込み
$news_query = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 6,
'category_name' => 'news', // カテゴリスラッグ
]);
// タグで絞り込み
$tag_query = new WP_Query([
'tag_slug__in' => ['wordpress', 'php'],
'posts_per_page' => 4,
]);
// カスタムフィールドで絞り込み(今日以降のイベント)
$event_query = new WP_Query([
'post_type' => 'event',
'posts_per_page' => 10,
'meta_key' => '_event_date',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => [[
'key' => '_event_date',
'value' => date('Y-m-d'),
'compare' => '>=',
'type' => 'DATE',
]],
]);
ステップ4:ループのカードレイアウト(CSS)
.post-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
.card {
background: #fff;
border: 1px solid #e2e4e7;
border-radius: 8px;
overflow: hidden;
transition: box-shadow 0.2s;
}
.card:hover {
box-shadow: 0 4px 16px rgba(0,0,0,0.12);
}
.card img {
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
}
.card-body {
padding: 1.25rem;
}
注意事項
- サブループ(WP_Query)を使った後は必ず
wp_reset_postdata()を呼んでください。メインループのグローバル$postが上書きされたままになります no_found_rows: trueはページネーション不要のサブループで使うとSQLのCOUNTクエリを省略して高速化できます- メインループのページネーションには
the_posts_pagination()かpaginate_links()を使います。サブループにはページネーションは通常設けません
まとめ
メインループは have_posts() + the_post() で動作します。独自のサブループは WP_Query で作成し、終了後に wp_reset_postdata() を呼ぶのが必須です。no_found_rows: true でページネーション不要な場合のパフォーマンスを改善できます。