WordPressのページネーションが動かなくてハマった

2016.11.15

WordPressのテンプレートを作成中、ページネーションの実装でハマったので備忘録です。

前提

バージョン:WordPress 4.5.4
プラグインを使わず、関数「paginate_links」を使用してページネーションを実装。

ハマった状況

ページネーションが、うんともすんとも動かない。
例えば、現在1ページ目を表示中で、ページネーションの「2」を押す。すると、画面の読み込みは実行されるものの、再度1ページ目の投稿が表示され、2ページ目以降の投稿が表示されない。

コード

function.php

function wp_pagination() {
global $wp_query, $paged;
$p_base = get_pagenum_link(1);
$p_format = 'page/%#%';
if($word = strpos($p_base, '?')){
$p_base = get_option(home).(substr(get_option(home), -1 ,1) === '/' ? '' : '/')
.'%_%'.substr($p_base, $word);
} else{
$p_base .= (substr($p_base, -1 ,1) === '/' ? '' : '/') .'%_%';
}
$paginate_links = paginate_links(array(
'base' => $p_base,
'format' => $p_format,
'total' => $wp_query->max_num_pages,
'prev_text' => '<',
'next_text' => '>',
'current' => ($paged ? $paged : 1),
'type' => 'array'
));
if($paginate_links && $wp_query->max_num_pages != 1){
echo '<ul>';
foreach ( $paginate_links as $pgl ) {var_dump($pgl);
if(strpos($pgl,"<span") !== false)
echo '<li class="current">'.$pgl.'</li>';
else
echo '<li>'.$pgl.'</li>';
}
echo '</ul>';
}
}

PHPファイル

$param = array(
'posts_per_page' => '15',
'post_type' => 'post',
'post_status' => 'publish',
'is_main_query' => false,
);
$my_query = new WP_Query($param);
if($my_query->have_posts()): while($my_query->have_posts()): $my_query->the_post();
?>
// ~中略~
<?php wp_pagination(); ?>

問題解決までの流れ

原因を調べていくと、以下のことが分かりました。

  • pegedの値がページに関係なく0になっている
  • pegedに数値を設定すると表示が変わる
  • パーマリンクの不一致

下で詳しく見ていきます。

pegedの値がページに関係なく0になっている

2ページ目を表示中、$wp_queryの内容を調べるとpagedの値が0でした。※内容はvar_dumpを使用して確認しました。

まず「$wp_query」とは、リクエスト上の情報を大量に抱えているオブジェクトで、表示する記事の件数やページ番号などを保持しています。
次に「paged」とは$wp_queryの持つ変数の1つで、現在表示しようとしているページ番号の値を持っています。例えば2ページ目を表示するのであれば「paged = 2」となっているはずです。

しかし、調べた結果2ページ目を表示中も「paged = 0」でした。つまり、表示しようとしているページの番号が認識されていないことになります。

$wp_queryの詳細は「関数リファレンス/WP Query」でご確認ください。

変数pegedに数値を設定すると表示が変わる

ここで痛恨のミスが発覚。$wp_queryに渡すパラメータの設定から、ページ数の設定が抜けていました。ページ数の設定を足すと以下になります。

$param = array(
'posts_per_page' => '15',
'post_type' => 'post',
'post_status' => 'publish',
'is_main_query' => false,
'paged' => get_query_var('paged'), // 漏れていた設定
);
$my_query = new WP_Query($param);
if($my_query->have_posts()): while($my_query->have_posts()): $my_query->the_post();
?>

関数get_query_var(‘paged’)を使って、現在表示しているページ番号を取得した上でpagedに設定してあげます。メインクエリとは別にクエリを作っているせいでややこしい事になってます。

まぁ、でもget_query_var(‘paged’)の値は0なので、結局2ページ目は表示されませんが。
※get_query_var(‘paged’)で取得している値は$wp_queryの変数pagedの値です。

と言うわけで、実験。pagedに数値を直接指定して動きを確認します。

$param = array(
'posts_per_page' => '15',
'post_type' => 'post',
'post_status' => 'publish',
'is_main_query' => false,
'paged' => 2, // 数値を直指定
);

ページ表示を試したところ、2ページ目の投稿一覧が表示されました。

数値を設定すれば意図した通り2ページ目を表示することが分かりました。となると、$wp_queryの変数pagedが常に0であることが原因と言えます。

パーマリンクの不一致

更に実験です。URLに

http://ドメイン/?paged=2

と指定するとどうなるでしょうか。結果、2ページ目の投稿一覧が表示されました。読み込まれたページのURLを見てみると

http://ドメイン/index.php/page/2

と表示されています。なんか余分な「index.php」が付着してます。なぜ。

管理画面からパーマリンクの設定を確認してみると、カスタム構造が以下のようになっていました。

/index.php/%year%/%monthnum%/%day%/%postname%/

…こんな設定にしたかな。ともかく、このパーマリンクが怪しそうです。

パーマリンクを

/index.php/%year%/%monthnum%/%day%/%postname%/ //変更前
/%year%/%monthnum%/%day%/%postname%/  //変更後

に変更したところ、URL「http://ドメイン/page/2」で2ページ目の表示に成功し、ページネーションは問題無く動きはじめました。

パーマリンクの設定とページングのURL指定が一致していない為、URL「http://ドメイン/page/2」へアクセスしてもページ番号は「2」と認識しなかったようです。

まとめ

今回の原因は2つ。

  • pagedの設定忘れ
  • パーマリンクの設定とページネーションのURL設定不一致

詰まった時は手当たり次第に修正せず、1つずつ理解しながら修正しないとバグ製造してしまうなと。調べる、理解する、原因の切り分け。大事です。

関連する記事