ページネーション(ページャー)が動かない!!wordPressの意外な落とし穴

あれ!?Wordpressでページ送りが動かない!な時も慌てず確認

ブログにページネーション(ページャー)を導入しようとしたとき相当慌ててしまいました。
どんなソースを書いても、どんなプラグインを入れても飛べないし、そもそもページ自体生成されない・・・ 半狂乱になって丸一日調べても全く解決策が出てこない・・・ドウシテコウナッタ
思考停止してしまった頭でぼんやりダッシュボードを眺めてて、ふと思いついた設定の変更ひとつで・・・・こともあろうにあっさり機能しました。

こんな体験談をもとにページャーが動かない問題の切り分けをしていきたいと思います。

1.ダッシュボードの表示設定を確認する

初歩的な箇所ですが一応確認しておきましょう。

pagenation1

件数より投稿数が少なければ当然ページネーションは表示されないし、もちろん2ページ目以降のページも生成されません。
ページネーションの作動テストをする際は1件表示にしてみましょう。

2.パラメータでoffsetを使っていないか

上層のページを飛ばして表示させるパラメータ「offset」を指定するとページネーションは動かない仕様のようです。
これは諦めるしかなさそうです。

3.ページネーションで自動生成されるurlでの表示を確認する

ページネーション以前に果たして表示するべきページは存在するのでしょうか?
なければ表示されないのも当然。まずはそこから確認していきましょう。

ページ送りをするということは間違いなく2ページ目はあるという前提なので、試しに下記のURLをブラウザに直接入力してみましょう。

2ページ目のURLをブラウザに直接入力

・投稿トップページなら「http://ドメイン名/page/2/」
・アーカイブページなら「「http://ドメイン名/カテゴリスラッグまたはタグスラッグ/page/2/」

/page/2…はページ送りが発生した際自動的に生成されるページです。
れが表示されなければページ送りに必要な次ページの生成に問題があると考えられます。

どうすればこの症状が発生するかをいくつか検証してみたのですが、下記の状態で発生することが確認できました。

2ページ目以降のURLが存在しないケース

・投稿トップページないしアーカイブページでサブループを使用
・ダッシュボードの「1ページに表示する最大投稿数」をサブループ内のposts_per_pageの表示数より大きく設定

原因はダッシュボードで設定した表示数から算出されたページ数を前提に1ページしか生成されなかったものに、サブループでページ送りを別に用意しても2ページ目以降は存在しない、という結果になったのでしょう。
他にも色々なケースでこの事象が発生するのでしょうが、ページ送りがうまくいっていないのが原因であることは確かなようです。

つまり投稿タイプのテンプレートではメインループ優先になり、サブループのページネーションは機能しないということでしょう

ちなみにこちらのサイトを参考にさせていただきました。

次のページが表示されない!WordPressでページ送りができないときの原因と対処方法

4.固定ページのサブループでページ送りに必要なコードは書かれているか

通常投稿ページでのメインループでのページネーションではさほどトラブルは発生しないと思います。
プラグインにしてもソースを公表してくれている方もほぼ投稿ページ前提で作っているはずだからです。
おそらくトラブルが発生するケースは固定ページ上ないしサブループで起こるものと推測されます。

固定ページサブループでうまく表示されないトラブル

・2ページ目以降が1ページ目と同じ表示になる。
・/page/2以降が存在せず404(Not Found)かトップページに飛ばされる

といったものはpagedをうまく取得できていないケースが多いようです。

pagedとは

ページ送りが発生した際、現在何ページにいるかの値が格納されている$wp_queryのパラメータ

ではページネーション対策されたサブループのコードを見ていきます。

wp_queryでのサブループ基本型(ページネーション使用前提)

<?php
    $paged = get_query_var('paged') ? get_query_var('paged') : 1 ;
        $args = array(
        'post_type' => 'post',
        'posts_per_page' => 2,
        'paged' => $paged
    );
    $my_query = new WP_Query($args);

    if( $my_query -> have_posts() ) :
        while($my_query -> have_posts()) : $my_query -> the_post();
?>

                    -----ループ処理-----
<?php
        endwhile;
    endif;
?>

上記は基本的な構文ですが、ページネーションを使用する上で大事なのは2行目と6行目になります。

2行目

$paged = get_query_var('paged') ? get_query_var('paged') : 1 ;

これは$wp_query内にある、現在何ページ目かを示す値「paged」をget_query_var()関数で拾って$pagedに代入しています。ちなみにれを詳細に書くとこうなります。

if (get_query_var('paged')) {
    $paged = get_query_var('paged');
} else {
    $paged = 1;
}

pagedの初期値は0になるのに2ページ目はpage/2というurlがつけられて、ページネーションに都合が悪くなるので「pagedの値が0の場合は1を代入する」という式になっています。

6行目

'paged' => $paged

先ほど取得(代入)した$pagedをループ処理用クエリのパラメータにあてます。
これでサブループの中に現在何ページ目かを認識させることができる、という訳です。

この件はこちらのフォーラムに詳しく書かれています。

WPフォーラム:WP_Queryでのページネーションについて

5.$pagedやmax_num_pagesの値は取れているか

前項で$pagedが何ページ目かを示す値という話をしましたが、ページネーションを作動させるにはもう一つの値が必要になります。
総ページ数を示すmax_num_pagesです。

mux_num_pagesとは

ページ送りが発生した際、投稿数と1ページの表示数から算出された総ページ数の値が格納されている$wp_queryのパラメータ

ページネーションのトラブル

・ページネーションが表示されない。
・表示されてもページ数が違う

こういったケースはmax_num_pagesのトラブルが考えられます。
この値は$wp_query内に格納されているので見てみましょう。(ダッシュボードの表示設定とサブループの表示設定とで値を変えて試してください。)

サブループで出力される2つのmax_num_pagesの値を見てみる

<pre>$wp_query->max_num_pages:<?php print_r($wp_query -> max_num_pages); ?></pre>
<?php
    $paged = get_query_var('paged') ? get_query_var('paged') : 1 ;
        $args = array(
        'post_type' => 'post',
        'posts_per_page' => 2,
        'paged' => $paged
    );
    $my_query = new WP_Query($args);
?>
    <pre>$my_query->max_num_pages:<?php print_r($my_query -> max_num_pages); ?></pre>
<?php
    if( $my_query -> have_posts() ) :
        while($my_query -> have_posts()) : $my_query -> the_post();
?>

                    -----ループ処理-----
<?php
        endwhile;
    endif;
?>

1行目は普通に$wp_queryから取得したもの。11行目はサブループ内で取得したもの。 それぞれ違う値が出力されるはずです。

さらに投稿ページ(post)と固定ページ(page)でも結果が変わるんです!

■投稿ページ

$wp_query -> max_num_pages・・・ダッシュボードで設定した値
$my_query -> max_num_pages・・・サブループで設定した値

■固定ページ

$wp_query -> max_num_pages・・・0
$my_query -> max_num_pages・・・サブループで設定した値

これでひとつ謎が解けました。
3項で挙げた表示ページ数の齟齬やサブループでページネーションが表示されないのはこれで説明がつきます。
つまり、ページネーションに適正なmax_num_pagesを渡してやれば機能するはずです。
固定ページのサブループで使用するにあたって2点ほど解決策を挙げておきますので参考にしてみてください。

wp_pagenaviプラグインの例

参考: WPフォーラム:WP_Queryでのページネーションについて

<?php if(function_exists('wp_pagenavi')) { wp_pagenavi(array('query'=>$my_query)); } ?>

ページネーションの関数にwp_queryの代わりにサブループで定義した$my_queryを当ててますね。

ノンプラグインのページネーションの例

参考: 寝ログ:WordPressにレスポンシブのページネーションを設置するカスタマイズ方法

<?php
    $paged = get_query_var('paged') ? get_query_var('paged') : 1 ;
        $args = array(
        'post_type' => 'post',
        'posts_per_page' => 2,
        'paged' => $paged
    );
    $my_query = new WP_Query($args);
    $max_num_pages = $my_query->max_num_pages;
?>
<?php
    if( $my_query -> have_posts() ) :
        while($my_query -> have_posts()) : $my_query -> the_post();
?>

                    -----ループ処理-----
<?php
        endwhile;
    endif;
?>
<?php
    if (function_exists('responsive_pagination')) {
    responsive_pagination($max_num_pages);
    }
?>

サブループで生成した$my_queryからmax_num_pagesを取得して、その値自体をページネーションに渡しています。

※追記(2016/06/15)

上記でも動きますが、wordpress側での設定した表示数(設定→表示設定→1ページに表示する最大投稿数)とサブループで設定したページ数(’posts_per_page’ => 2,など)の差によって記事のないページが生成され、そのページにもリンクは張られてしまいます。

例えば3記事の投稿があって、wordpress側で1ページ1記事表示、サブループ側で1ページ2記事表示の設定をした場合、ページ送りのページはwordpress側の設定によって生成されるので3ページ(/page/3/)、でも実際は2ページになり、空白の3ページ目ができてしまいます。

リンクは張られなければ問題はないのですが、例で挙げた寝ログ様のページャーですと空白の3ページ目にもリンクが作られてしまうので、抑制するのにfunctions.phpを下記のように加工しておいたほうが良いでしょう。(自分で組んだコードではないので全文掲載は控えさせていただきます。)

//1つ進む
if( $paged != $pages){ //現在のページが$max_num_pagesから参照した最後のページではない場合、現在ページ+1ページ目のリンクを張る
  echo '<li class="next"><a href="'.get_pagenum_link($paged + 1).'"><span>Next</span></a></li>';
}else{ //そうでなければ(最後のページなら)現在のページのリンクを張る
  echo '<li class="next"><a href="'.get_pagenum_link($paged).'"><span>Next</span></a></li>';
}

1つ戻る、の部分はそのままで影響はありませんが、気になるようでしたら同様に加工しておいても良いかもしれません。

6.「フロントページの表示」で固定ページを選択していないか

実はここまで調べてもまったく改善せず頭を抱えたのですが、最後に思わぬ落とし穴がありました・・・

pagenation1

ブログ構築にあたってトップページをindex.phpではなくfront-page.phpにしていたのですが、まんまと固定ページを選択していました・・・

これまで投稿ページと固定ページの違いなんてカテゴリやタグが使えるか使えない程度くらいでしか考えてなく、形式的に使い分けていましたが、$wp_queryが出力するデータいかんで用途や用法がガラリと変わるんですねぇ。とても勉強になりました。

まとめ:理屈が分かれば怖くない!

ページネーションの問題を自分なりに切り分けて解説してみました。
いくらか実証を繰り返してみたので、解釈に多少の差異はあるかもしれませんがこの記事で挙げた条件と対応ではしっかり動くはずです。
ソースによってはfuncitons.phpを改変する必要があるかも知れませんが、基本的にpagedとmax_num_pagesの値の問題だと思います。

ちなみにカスタム投稿タイプでも同様の対応で問題ありませんでした。

5件のコメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA