WordPressの一覧ページで記事をランダムに表示する方法を紹介します。固定の表示順にしたくない場合や、関連コンテンツをランダムに見せたい場合に使えます。メインループ・WP_Query の2通りと、ランダム表示につきものの「2ページ目以降で重複する」問題への実用的な対処まで解説します。
pre_get_postsでアーカイブのメインループをランダム表示にするWP_Queryでランダムな記事一覧を取得する- カテゴリーを絞ってランダム表示する
ORDER BY RAND()のパフォーマンス注意とキャッシュ- 2ページ目以降の重複を防ぐ方法
メインループをランダム表示にする(pre_get_posts)
カテゴリーページなどのアーカイブをランダム表示にするには、まず記事を表示するテンプレート(index.php・archive.php 等)にループを用意します。一覧の各記事は h2 以下の見出しにします(1ページに h1 を複数置かないため)。
<?php if (have_posts()) : while (have_posts()) : the_post(); ?> <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2> <?php the_content(); ?> <?php endwhile; else : ?> <p>記事が見つかりませんでした。</p> <?php endif; ?>
次に functions.php で、pre_get_posts を使ってアーカイブのメインクエリだけ表示順をランダムにします。
function my_random_archive($query) {
// 管理画面・サブクエリ・メインでないクエリは対象外(誤動作防止)
if (is_admin() || !$query->is_main_query()) {
return;
}
if ($query->is_archive()) {
$query->set('orderby', 'rand'); // 表示順をランダムに
}
}
add_action('pre_get_posts', 'my_random_archive');
is_admin() と is_main_query() のガードは必須pre_get_posts は管理画面の投稿一覧やサイドバーのサブクエリなど、あらゆるクエリで実行されます。ガードを入れないと管理画面の並び順まで壊れるため、必ず対象を絞ってください。is_archive() を is_home() に変えればトップページ、is_category() なら特定カテゴリーだけ、のように調整できます。WP_Query でランダムな記事一覧を取得する
固定ページの中に記事一覧を差し込みたい場合などは、メインループではなく WP_Query でループを作ります。最後に wp_reset_postdata() でリセットするのを忘れないようにします。
<?php
$args = array(
'orderby' => 'rand', // ランダム表示
'posts_per_page' => 5, // 表示件数
);
$random_query = new WP_Query($args);
if ($random_query->have_posts()) :
while ($random_query->have_posts()) : $random_query->the_post(); ?>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_content();
endwhile;
else : ?>
<p>記事が見つかりませんでした。</p>
<?php endif;
wp_reset_postdata(); // メインループに影響しないようリセット
?>
カテゴリーを絞ってランダム表示する
特定カテゴリーの中からランダムに表示するには、category_name(スラッグ)または cat(ID)を加えます。
$args = array( 'category_name' => 'news', // カテゴリースラッグ(IDなら 'cat' => 5) 'orderby' => 'rand', 'posts_per_page' => 3, ); $query = new WP_Query($args);
カテゴリーの取得や絞り込みの全体像は記事のカテゴリーを取得する方法(WP_Query 対応)、複雑な条件での取得はWP_Queryで複雑な条件検索を実装する方法も参考になります。
ORDER BY RAND() のパフォーマンスに注意
orderby => 'rand' は内部で ORDER BY RAND() を実行します。これは全行に乱数を割り当ててソートするため、記事数が多いサイトでは負荷が大きく、ページ表示のたびにDBへ問い合わせが走ります。表示件数を絞る、結果をキャッシュする、のどちらか(または両方)を必ず併用してください。下のようにトランジェントAPIでランダムな結果を一定時間キャッシュすれば、毎回 ORDER BY RAND() を実行せずに済み、後述の重複問題も同時に防げます。
<?php
// ランダムな投稿を1時間キャッシュ(毎回の ORDER BY RAND() を回避)
$random_posts = get_transient('random_posts');
if ($random_posts === false) {
$random_posts = get_posts(array(
'orderby' => 'rand',
'numberposts' => 5,
));
set_transient('random_posts', $random_posts, HOUR_IN_SECONDS); // 1時間
}
foreach ($random_posts as $post) {
setup_postdata($post); ?>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php }
wp_reset_postdata();
2ページ目以降で記事が重複する問題と対処
ランダム表示には構造的な弱点があります。ページを読み込むたびに並び順が変わるため、ページネーションすると2ページ目以降に1ページ目と同じ記事が再び現れることがあります。これは ORDER BY RAND() がリクエストごとに別の順序を返す仕様によるものです。
- キャッシュで順序を固定:上のトランジェント方式なら、キャッシュ期間中は同じ順序になり重複しません(実用上おすすめ)
- ページネーションせず少数を表示:「おすすめ記事5件」のような用途なら
posts_per_pageを小さくして1ページに収める - 全件を1ページに:
posts_per_page => -1で全記事を表示(※記事数が多いと重いので小規模サイト向け)
そもそもページネーションが目的なら、ランダムではなく通常の並び順にしてプラグインなしのページネーション実装方法を使うのが安全です。全記事の一覧化は全記事一覧ページを作成する方法、関連記事のランダム表示はプラグインなしで関連記事を表示する方法も合わせてご覧ください。
よくある質問(FAQ)
WP_Query の引数に 'orderby' => 'rand' を設定します。例:new WP_Query(["orderby" => "rand", "posts_per_page" => 5]);。アーカイブ全体をランダムにするなら pre_get_posts で $query->set('orderby', 'rand') を使います。get_transient() / set_transient() で結果をキャッシュします。$posts = get_transient("random_posts"); if ($posts === false) { $posts = get_posts(["orderby"=>"rand","numberposts"=>5]); set_transient("random_posts", $posts, HOUR_IN_SECONDS); } で1時間キャッシュでき、毎回の ORDER BY RAND() を避けつつ順序も安定します。テーマやプラグインのキャッシュ機能を使っている場合は、対象ページを除外設定が必要なこともあります。WP_Query に category_name(スラッグ)または cat(ID)と orderby を組み合わせます。例:new WP_Query(["category_name" => "news", "orderby" => "rand", "posts_per_page" => 3]);。まとめ
- アーカイブ全体:
pre_get_posts+orderby => rand(is_admin()等のガード必須) - 任意の場所:
WP_Query+wp_reset_postdata() - パフォーマンス:
ORDER BY RAND()は重い → 件数を絞る+トランジェントでキャッシュ - 重複対策:キャッシュで順序固定が実用的。ページネーションが目的なら通常順+ページネーションを使う
ランダム表示は手軽ですが負荷と重複に注意が必要です。キャッシュと表示件数を調整して、軽快に動くランダム表示を実装してみてください。

