べんりワザ・WordPressのテンプレートと投稿の取得

WordPressのページ送り(ページネーション)の出し方

投稿一覧のページ送りを出す方法。1行で済むthe_posts_pagination、WP_Queryのサブループで動かすpagedの指定、2ページ目が404になるときの原因と直し方をまとめました。

投稿一覧のページ送りは、メインループなら1行で出せます。

<?php the_posts_pagination(); ?>

つまずくのはWP_Queryで作った一覧のほうです。こちらは「今が何ページ目か」をクエリに教える必要があります。順に見ていきます。

メインループのページ送り

home.phparchive.phpcategory.phpなど、そのページの主役の一覧にはthe_posts_pagination()を使います。見た目の文言も指定できます。

<?php
the_posts_pagination([
  'mid_size'  => 2,        // 現在ページの左右に出す番号の数
  'prev_text' => '前へ',
  'next_text' => '次へ',
  'screen_reader_text' => 'ページ送り',   // 見出し(読み上げ用)
]);
?>

出力されるHTMLはこんな形です。CSSはこのクラスに当てます。

<nav class="navigation pagination">
  <div class="nav-links">
    <span aria-current="page" class="page-numbers current">1</span>
    <a class="page-numbers" href="…/page/2/">2</a>
    <a class="next page-numbers" href="…/page/2/">次へ</a>
  </div>
</nav>
.pagination .nav-links { display: flex; gap: 0.5rem; justify-content: center; }
.pagination .page-numbers {
  padding: 0.4em 0.8em;
  border: 1px solid #ddd;
  border-radius: 6px;
  text-decoration: none;
}
.pagination .page-numbers.current { background: #333; color: #fff; }

「前へ/次へ」だけで十分なら、さらに軽い2つの関数もあります。

<?php previous_posts_link('新しい記事へ'); ?>
<?php next_posts_link('古い記事へ'); ?>

WP_Queryのサブループのページ送り

自分で作ったクエリは、「今が何ページ目か」を渡さないと永遠に1ページ目を表示します。ここが最大のつまずきポイントです。

<?php
$paged = max(1, (int) get_query_var('paged'));   // 今のページ番号(無ければ1)

$query = new WP_Query([
  'post_type'      => 'shohin',
  'posts_per_page' => 12,
  'paged'          => $paged,                    // ← これが必須
]);
?>
<?php if ($query->have_posts()) : ?>
  <div class="cards">
    <?php while ($query->have_posts()) : $query->the_post(); ?>
      <article class="card"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></article>
    <?php endwhile; ?>
  </div>

  <?php
  // ページ送りの出力(メインクエリではないので自分で組む)
  echo '<nav class="pagination">';
  echo paginate_links([
    'total'     => $query->max_num_pages,   // 総ページ数
    'current'   => $paged,
    'mid_size'  => 2,
    'prev_text' => '前へ',
    'next_text' => '次へ',
  ]);
  echo '</nav>';
  ?>
<?php endif; ?>
<?php wp_reset_postdata(); ?>

覚えることは3つです。

  • クエリに'paged'を渡すget_query_var('paged')から取る)
  • paginate_links()totalcurrentを渡すtotal$query->max_num_pages
  • 最後にwp_reset_postdata()
べんりワザループの外で投稿を取得する方法(WP_Query)サブループの基本と後始末の理由はこちら

2ページ目が404になるとき

原因はだいたい次の3つです。上から確認します。

1. 固定ページの中のサブループ(pagedではなくpage)

固定ページ(page.phppage-shohin.php)の中でサブループを回すときだけ、ページ番号はpagedではなくpageというクエリ変数に入ります。固定ページのpagedはすでに別の用途で使われているためです。

<?php
$paged = max(1, (int) get_query_var('paged'), (int) get_query_var('page'));
?>

max()で両方から拾っておけば、固定ページでもアーカイブでも同じコードが動きます。

2. パーマリンクのルールが古い

投稿タイプやタクソノミーを追加したあとは、URLの変換ルールを作り直す必要があります。管理画面の「設定」→「パーマリンク」を開いて「変更を保存」を押すだけで再生成されます(設定を変えなくてOK)。カスタム投稿タイプ関連の404は、これで直ることがかなり多いです。

3. 1ページ目と件数の食い違い

'posts_per_page' => -1(全件取得)のままpaginate_links()を使うと、総ページ数が1のままになりページ送りが機能しません。ページ送りを付ける一覧では、必ず件数を指定します。

1ページに出す件数を変える

  • サイト全体——「設定」→「表示設定」の「1ページに表示する最大投稿数」
  • 特定のアーカイブだけ——pre_get_postsで指定
function my_posts_per_page($query) {
  if (is_admin() || !$query->is_main_query()) {
    return;
  }
  if (is_post_type_archive('shohin')) {
    $query->set('posts_per_page', 12);
  }
}
add_action('pre_get_posts', 'my_posts_per_page');

メインの一覧の件数はこの方法で変えるのが正解です。WP_Queryで作り直すとページ送りやパンくずと食い違いが出ます。

「もっと見る」ボタンにしたいとき

番号ではなくボタンで追加読みこみしたい場合も、土台は同じです。paginate_links()の代わりにnext_posts_link()のURLを使い、JavaScriptで次ページのHTMLを取ってきて差しこみます。まずはページ送りとして正しく動く状態を作ってから、その上に載せるのが安全な進め方です。

まとめ

  1. メインループのページ送りはthe_posts_pagination()の1行。文言は引数で調整
  2. WP_Queryでは'paged' => get_query_var('paged')paginate_links()totalが必須
  3. 404のときは固定ページならpage変数、それ以外はパーマリンク設定の再保存を試す
  4. メインの一覧の件数はpre_get_postsで変える。クエリを作り直さない

ページ送りが正しく動くと、記事が増えても回遊できるサイトになります。

よくある質問

ページネーションを出す最短の方法は?
メインループの一覧なら、ループを閉じたあとにthe_posts_pagination()を1行書くだけです。引数でprev_textやmid_sizeを調整できます。
WP_Queryで作った一覧のページ送りが動きません
クエリの引数に'paged' => max(1, get_query_var('paged'))を渡していないと、常に1ページ目が表示されます。出力はpaginate_links()に'total' => $query->max_num_pagesを渡して作ります。
2ページ目にいくと404になります
固定ページの中でサブループを回している場合は、get_query_var('paged')ではなくget_query_var('page')を使います。それ以外では、パーマリンク設定の画面を開いて「変更を保存」を押すとルールが再生成されて直ることが多いです。
1ページに表示する件数を変えたいです
サイト全体は「設定」→「表示設定」の「1ページに表示する最大投稿数」で変えます。特定のアーカイブだけ変えたいときはpre_get_postsでposts_per_pageを指定します。