あれ!?Wordpressでページ送りが動かない!な時も慌てず確認
ブログにページネーション(ページャー)を導入しようとしたとき相当慌ててしまいました。
どんなソースを書いても、どんなプラグインを入れても飛べないし、そもそもページ自体生成されない・・・ 半狂乱になって丸一日調べても全く解決策が出てこない・・・ドウシテコウナッタ
思考停止してしまった頭でぼんやりダッシュボードを眺めてて、ふと思いついた設定の変更ひとつで・・・・こともあろうにあっさり機能しました。
こんな体験談をもとにページャーが動かない問題の切り分けをしていきたいと思います。
目次
1.ダッシュボードの表示設定を確認する
初歩的な箇所ですが一応確認しておきましょう。
件数より投稿数が少なければ当然ページネーションは表示されないし、もちろん2ページ目以降のページも生成されません。
ページネーションの作動テストをする際は1件表示にしてみましょう。
2.パラメータでoffsetを使っていないか
上層のページを飛ばして表示させるパラメータ「offset」を指定するとページネーションは動かない仕様のようです。
これは諦めるしかなさそうです。
3.ページネーションで自動生成されるurlでの表示を確認する
ページネーション以前に果たして表示するべきページは存在するのでしょうか?
なければ表示されないのも当然。まずはそこから確認していきましょう。
ページ送りをするということは間違いなく2ページ目はあるという前提なので、試しに下記のURLをブラウザに直接入力してみましょう。
2ページ目のURLをブラウザに直接入力
・アーカイブページなら「「http://ドメイン名/カテゴリスラッグまたはタグスラッグ/page/2/」
/page/2…はページ送りが発生した際自動的に生成されるページです。
れが表示されなければページ送りに必要な次ページの生成に問題があると考えられます。
どうすればこの症状が発生するかをいくつか検証してみたのですが、下記の状態で発生することが確認できました。
2ページ目以降のURLが存在しないケース
・ダッシュボードの「1ページに表示する最大投稿数」をサブループ内のposts_per_pageの表示数より大きく設定
原因はダッシュボードで設定した表示数から算出されたページ数を前提に1ページしか生成されなかったものに、サブループでページ送りを別に用意しても2ページ目以降は存在しない、という結果になったのでしょう。
他にも色々なケースでこの事象が発生するのでしょうが、ページ送りがうまくいっていないのが原因であることは確かなようです。
つまり投稿タイプのテンプレートではメインループ優先になり、サブループのページネーションは機能しないということでしょう
ちなみにこちらのサイトを参考にさせていただきました。
4.固定ページのサブループでページ送りに必要なコードは書かれているか
通常投稿ページでのメインループでのページネーションではさほどトラブルは発生しないと思います。
プラグインにしてもソースを公表してくれている方もほぼ投稿ページ前提で作っているはずだからです。
おそらくトラブルが発生するケースは固定ページ上ないしサブループで起こるものと推測されます。
固定ページサブループでうまく表示されないトラブル
・/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をループ処理用クエリのパラメータにあてます。
これでサブループの中に現在何ページ目かを認識させることができる、という訳です。
この件はこちらのフォーラムに詳しく書かれています。
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)でも結果が変わるんです!
■投稿ページ
$my_query -> max_num_pages・・・サブループで設定した値
■固定ページ
$my_query -> max_num_pages・・・サブループで設定した値
これでひとつ謎が解けました。
3項で挙げた表示ページ数の齟齬やサブループでページネーションが表示されないのはこれで説明がつきます。
つまり、ページネーションに適正なmax_num_pagesを渡してやれば機能するはずです。
固定ページのサブループで使用するにあたって2点ほど解決策を挙げておきますので参考にしてみてください。
参考: 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.「フロントページの表示」で固定ページを選択していないか
実はここまで調べてもまったく改善せず頭を抱えたのですが、最後に思わぬ落とし穴がありました・・・
ブログ構築にあたってトップページをindex.phpではなくfront-page.phpにしていたのですが、まんまと固定ページを選択していました・・・
これまで投稿ページと固定ページの違いなんてカテゴリやタグが使えるか使えない程度くらいでしか考えてなく、形式的に使い分けていましたが、$wp_queryが出力するデータいかんで用途や用法がガラリと変わるんですねぇ。とても勉強になりました。
まとめ:理屈が分かれば怖くない!
ページネーションの問題を自分なりに切り分けて解説してみました。
いくらか実証を繰り返してみたので、解釈に多少の差異はあるかもしれませんがこの記事で挙げた条件と対応ではしっかり動くはずです。
ソースによってはfuncitons.phpを改変する必要があるかも知れませんが、基本的にpagedとmax_num_pagesの値の問題だと思います。
ちなみにカスタム投稿タイプでも同様の対応で問題ありませんでした。
[…] あれ!?Wordpressでページ送りが動かない!な時も慌てず確認 […]
[…] 号がうまく伝わらない(?)といいますか、2ページ目であることをきちんと処理できていないのが原因なので、WP_Queryにそれを含めます。 この解決法はここから引っ張ってきました。 index.php […]
[…] ページャーで空のページがある。 @See http://xtra-blog.net/pagination/ […]
[…] ページネーション(ページャー)が動かない!!wordPressの意外な落とし穴 […]
[…] ページネーション(ページャー)が動かない!!wordPressの意外な落とし穴 | XTRA BLOGログにページネーション(ページャー)を導入しようとしたとき相当慌ててしまいました。 どんなソー […]
offsetがあるとダメなんですね。。。。。。。。
すごい原因探しました。