ページ送りが動かない主な原因
WP_Queryでページ送りが動かないときは、まず paged がクエリへ渡っているかを確認します。次に、paginate_links() の total と current、no_found_rows、offset、固定フロントページの page、pre_get_posts の干渉を順に見ます。
特に多いのは、paged を渡さず2ページ目以降でも1ページ目と同じ記事が出るケースです。リンク生成だけでなく、現在ページをWP_Queryへ渡す処理まで確認してください。
よくある症状を先に整理する
総件数やページ数だけが合わない場合は、posts_per_page、管理画面の表示件数、別フックによる上書きを確認してください。ページを進めると同じ記事が出る場合は、paged、offset、複数ループや除外条件を確認すると、症状に合う切り分けができます。
同じ「ページ送りが動かない」でも、現在ページ、総ページ数、リンクURL、別フックのどこがずれたかで直す場所が変わります。まず症状を次の表へ当てはめます。
| 症状 | 最初に疑う場所 | よくある原因 |
|---|---|---|
| 2ページ目でも同じ記事が出る | paged の渡し忘れ | 現在ページ番号がWP_Queryに入っていない |
| ページネーションリンクが出ない | max_num_pages / total | 総ページ数が1扱いになっている |
| 2ページ目が404になる | 固定フロントページ / rewrite / main query | paged ではなく page を見る必要がある場合がある |
| ページ数が合わない | offset / posts_per_page | 件数計算と取得位置がずれている |
| 以前は動いていたのに崩れた | pre_get_posts / 追加条件 | 別の処理がクエリを書き換えている |
最初に確認する順番
表示に使っているWP_Queryへ現在ページ番号が渡っているか、リンク生成側が同じ現在ページ番号と総ページ数を使っているか、という順で切り分けます。固定フロントページやoffsetなどは、その後に確認します。
原因を切り分ける手順
- 1URLとget_query_var( 'paged' )の現在ページ番号を照合する
- 2同じ正の整数をWP_Queryのpagedへ渡す
- 3対象クエリのmax_num_pagesをpaginate_links()のtotalへ渡す
- 4固定フロントページならpageも別に確認する
- 5リンクのhrefとrewrite・permalinkを確認する
- 6no_found_rows・offset・別フックを1つずつ外す
まずは最小構成でページ送りを確認する
原因を切り分けるときは、条件を減らした最小構成で確認します。tax_query、meta_query、複雑な並び順、offset などをいったん外し、通常の投稿を少ない件数で取得して、ページ送りが動くかを確認します。
次のコードは、現在ページ番号をpagedへ渡し、paginate_links()でリンクを出す最小例です。まず一般的な一覧テンプレートで確認します。
原因を切り分けるための一時的な確認コードです。ローカルなどの検証環境だけで使い、確認後は削除してください。
$paged = max( 1, absint( get_query_var( 'paged' ) ) ); $args = [ 'post_type' => 'post', 'posts_per_page' => 5, 'paged' => $paged,]; $the_query = new WP_Query( $args ); if ( $the_query->have_posts() ) { echo '<ul>'; while ( $the_query->have_posts() ) { $the_query->the_post(); echo '<li><a href="' . esc_url( get_permalink() ) . '">'; echo esc_html( get_the_title() ); echo '</a></li>'; } echo '</ul>'; $pagination = paginate_links( [ 'total' => $the_query->max_num_pages, 'current' => $paged, 'type' => 'list', ] ); if ( $pagination ) { echo '<nav aria-label="投稿一覧のページ送り">'; echo wp_kses_post( $pagination ); echo '</nav>'; }} wp_reset_postdata();このコードのポイントは、get_query_var( ‘paged’ ) の値を1以上の整数へ正規化し、その値をWP_Queryの paged に渡している点です。リンクを表示する paginate_links() だけを書いても、WP_Query側に現在ページ番号が入っていなければ、取得される記事は変わりません。
もうひとつ重要なのは、paginate_links() の total に $the_query->max_num_pages を渡している点です。カスタムループでは、メインクエリのページ数ではなく、自分で作ったWP_Queryの総ページ数を見る必要があります。
また、paginate_links()の戻り値がある場合だけ、用途が分かるnav内へ出力しています。総ページ数が1なら空のナビゲーションを残しません。

1ページ目と2ページ目で、URL、現在ページ表示、投稿タイトルがそれぞれ変わることを確認します。URLだけ変わって投稿が同じならpaged、リンク自体が出ないならmax_num_pagesとリンク生成側を先に調べます。
ページ送りが壊れる原因を順に確認する
最小構成でページ送りが動いたら、現在ページ、固定フロントページ、総ページ数、offset、外部処理の順に実際の条件を戻します。
原因1:pagedをWP_Queryに渡していない
2ページ目をクリックしても同じ記事が表示される場合、最初に疑うのは paged の渡し忘れです。ページネーションリンクのURLが変わっていても、WP_Queryの条件が毎回同じなら、取得される記事も毎回同じになります。
pagedは、WP_Queryに「何ページ目の投稿を取得するか」を伝える引数です。get_query_var( ‘paged’ )を1以上の整数にし、同じ値を$args[‘paged’]とpaginate_links()のcurrentへ渡します。現在ページを取得するだけ、またはリンクを表示するだけでは投稿は切り替わりません。
原因2:固定フロントページでpagedではなくpageを見る必要がある
通常の一覧ページでは get_query_var( ‘paged’, 1 ) で現在ページを扱うことが多いです。ただし、固定フロントページ上のページテンプレートで独自のWP_Queryを動かす場合は、paged ではなく page を確認した方がよいケースがあります。
WordPress公式のget_query_var()リファレンスも確認してください。固定フロントページに設定したページテンプレートでクエリを動かす場合は、get_query_var( ‘page’ ) を使う説明があります。トップページだけページ送りが崩れる場合は、この違いを疑います。
引数や処理の一部分だけを示した例です。このまま単独で貼らず、テンプレート内のWP_Queryとループへ組み込んでください。
$paged = max( 1, absint( get_query_var( 'page' ) ) ); $args = [ 'post_type' => 'post', 'posts_per_page' => 5, 'paged' => $paged,]; $the_query = new WP_Query( $args );このコードのポイントは、WP_Queryに渡す引数名は paged のままですが、現在ページ番号の取得元として page を見ている点です。固定フロントページでのみ動かない場合は、通常のアーカイブページと同じように paged だけを見ていないか確認してください。

WordPressの表示設定でホームページに指定した固定ページと、実際に確認しているフロントページを照合します。そのうえでpageとpagedの実値をログへ出し、どちらが現在ページ番号を持つか確認します。
原因3:2ページ目のURLが404になる
存在するはずの2ページ目が404になる場合は、現在ページ番号だけでなく、生成されたリンクのURL、rewrite・パーマリンク、メインクエリのページ判定を分けて確認します。投稿数や絞り込み条件が変わり、最終ページを超えたURLが404になるのは正常な挙動です。
リンクのhrefが意図したURLになっているか、そのURLを開いたときに対象クエリのpagedまたはpageが何になっているかを照合してください。パーマリンク設定を保存し直す前に、問題がリンク生成にあるのか、リライトルールにあるのかをログで切り分けます。
404を切り分ける順番
- 12ページ目リンクのhrefが、意図したURLになっているか確認する
- 2404になるURLを開き、pagedとpageの実値をログへ出す
- 3現在ページ番号と対象WP_Queryのmax_num_pagesを比べる
- 4offset・複雑な絞り込み・追加フックを一度外し、最小構成で再確認する
- 5存在するページまで404になる場合は、メインクエリの表示件数と条件、リライトルール、パーマリンク設定を順に確認する
- 6修正後は1ページ目・2ページ目・最終ページ・最終ページを1つ超えたURLを確認する
原因4:paginate_linksのtotalとcurrentが違っている
ページネーションリンクを作るときは、paginate_links() の total と current が重要です。total は総ページ数、current は現在ページ番号です。ここが空だったり、メインクエリの値を見ていたりすると、リンクが出ない、現在ページが合わない、といった症状につながります。
paginate_links()にはメインクエリを前提にしたtotalとcurrentの既定値があります。カスタムループでは、最小完全コードのように、独自WP_Queryのmax_num_pagesと、同じクエリへ渡した現在ページ番号を明示してください。リンク先URLがおかしい場合にだけ、baseとformatも確認します。
総ページ数が2未満ならpaginate_links()はリンクを返しません。posts_per_page => -1やnopaging => trueも通常のページ分割を行わないため、リンクが出ないときは取得条件も確認してください。
原因5:no_found_rowsやoffsetでページ数の計算が崩れている
no_found_rows => trueは、総件数を求めるためのSQL計算を省略します。そのため通常のfound_postsとmax_num_pagesを得られず、総ページ数を使うページ送りでは使いません。
offsetは取得開始位置をずらしますが、found_postsから自動では差し引かれません。pagedと併用する場合は、取得位置、最終ページ、重複・欠落を自分で調整する必要があります。まずoffsetを外して直るか確認してください。
| 引数 | ページネーションへの影響 | 確認ポイント |
|---|---|---|
no_found_rows | 総ページ数の計算に影響しやすい | ページネーションが必要な一覧で true にしていないか見る |
offset | 取得開始位置とページ計算がずれやすい | ページ送りが必要な一覧では一度外して確認する |
posts_per_page | 1ページあたりの件数を決める | 管理画面設定や他のフックで上書きされていないか見る |
原因6:pre_get_postsの対象条件が広すぎる
pre_get_posts は、クエリが実行される前に条件を変更できる便利なフックです。一方で、対象を絞らずに使うと、メインクエリだけでなくサイドバーやカスタムループなど、意図しないクエリに影響することがあります。
ページネーションが以前は動いていたのに、別の絞り込み処理を追加してから崩れた場合は、pre_get_posts を確認してください。公式資料でも、is_admin() や $query->is_main_query() などで対象のクエリを絞る重要性が説明されています。
子テーマのfunctions.phpまたは機能プラグインに置く例です。対象画面と実行条件を確認し、検証環境で試してから本番へ反映してください。
add_action( 'pre_get_posts', function ( $query ) { if ( is_admin() || ! $query->is_main_query() ) { return; } if ( $query->is_post_type_archive( 'event' ) ) { $query->set( 'posts_per_page', 10 ); }} );pre_get_posts自体は複数のクエリに対して実行されますが、この例は最初に管理画面とメインクエリ以外を除外します。そのため通常のセカンダリWP_Queryはこの処理の対象になりません。実際のコードにこの限定がない、または別の条件が広すぎる場合は、意図しないクエリまで変更されていないか確認してください。
1ページ目だけ件数や重複が違う場合は、先頭固定表示も確認します。ignore_sticky_postsは先頭への特別扱いを無効にする指定で、条件に一致する固定投稿そのものを除外する指定ではありません。複数ループ、offset、除外条件が重なっていないかも確認してください。
確認用に出しておきたい値
原因が分からないときは、現在ページ番号、総ページ数、総件数、最終的なクエリ変数を確認します。ブラウザでは生成されたページリンクのhrefも見て、取得側とリンク生成側を分けてください。
本番環境で画面にそのまま出すのは避け、検証環境や一時的なデバッグとして確認してください。数値が期待と違う場合、取得側のWP_Queryか、リンク生成側のどちらかにずれがあります。
原因を切り分けるための一時的な確認コードです。ローカルなどの検証環境だけで使い、確認後は削除してください。
error_log( 'paged: ' . $paged );error_log( 'max_num_pages: ' . $the_query->max_num_pages );error_log( 'found_posts: ' . $the_query->found_posts );error_log( 'query_vars: ' . wp_json_encode( $the_query->query_vars ) );このコードのポイントは、ページ番号、総ページ数、総件数を分けて見ている点です。paged が常に1なら、現在ページ番号の取得処理に問題があります。max_num_pages が1のままなら、総ページ数の計算と取得条件を確認します。
WP Query Builderで確認できるのは、paged、posts_per_page、offset、no_found_rowsなどの$argsです。現在ページ番号の取得とpaginate_links()のHTML出力、rewrite、pre_get_postsの影響はテンプレートやフック側で確認してください。
公式資料で確認したいポイント
WP_Queryのページネーションは、複数の関数と引数が関係します。paged はWP_Query側、paginate_links() はリンク生成側、get_query_var() は現在ページ番号の取得、pre_get_posts はクエリ変更の影響範囲を確認するために見ます。
公式資料を開くときは、全部を一度に読むより、今起きている症状に合わせて確認する場所を分けると読みやすくなります。2ページ目が同じならWP_Queryの paged、リンクが出ないなら paginate_links() の total と current、フック追加後に崩れたなら pre_get_posts を見ます。
公式リンク
公式ドキュメント
1ページ目からページ超過まで動作確認する
取得側のWP_Query、リンク生成側、固定フロントページ、フックの影響を分けて確認します。最小構成で1ページ目と2ページ目の投稿が入れ替わったら、絞り込み、並び順、offset、高速化用の引数を1つずつ戻します。
修正後に確認すること
- 1ページ目と2ページ目でURL・現在ページ・投稿が変わる
- 対象クエリのmax_num_pagesをtotalへ使っている
- 最終ページまで重複と欠落がない
- 最終ページを超えたURLは意図どおり404になる
- 固定フロントページと通常一覧をそれぞれ確認した
この記事の検証情報
検証環境
- WordPress
- 7.1
- PHP
- 8.3.33
- テーマ
- wpq-media + DDEV
- 対象
- カスタム投稿 / taxonomy / meta_query
更新履歴
- 2026年8月24日 初回公開
この記事を活用する
あとで見返す・共有する
お気に入りに保存できます。役に立ったポイントは、いいねや共有で教えてください。


