あんまりやりたくないパターンだけど、WordPressの固定ページテンプレート内で記事一覧を表示させ、あまつさえページネーションもつけたいというときがある。
このページネーションの2ページ目以降が404になってはまったけど、動かない原因と対策がわかったのでメモ。
なぜ404となるのか
固定ページ内でページネーションを使うと404になる原因についてですが、たぶん以下のような感じだと思います。
- ページネーションの仕様上、2ページ目とかのURLに、/page/2/とかがつく
- 例えば/hoge/page/2/のようなパーマリンクになる
- そんな固定ページはないので、404になる。
まぁ、固定ページでそもそもページネーションできるようになっていないんでしょうね。そりゃそうよ。
解決策
/page/2/みたいにならなければいいんじゃないか。
WordPressでは、上記のようなURL構造でなくとも、?page=2みたいなパラメータでもページネーションになります。
ただし、デフォルトだと?page=2にアクセスしても、/page/2/にリダイレクトされてしまう。
よって、ページネーションのURLの形式を?page=2にして、なおかつ勝手にリダイレクトさせないようにすればOK。
実装
functions.phpに以下を記述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
add_filter('redirect_canonical','my_disable_redirect_canonical'); function my_disable_redirect_canonical( $redirect_url ) { if ( is_archive() ){ $subject = $redirect_url; $pattern = '/\/page\//'; // URLに「/page/」があるかチェック preg_match($pattern, $subject, $matches); if ($matches){ //リクエストURLに「/page/」があれば、リダイレクトしない。 $redirect_url = false; return $redirect_url; } } } |
続いて、ページネーションのほうは以下のようにする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?php $paged = (int) get_query_var('paged'); // $pagedを定義。これがないとページネーションが動かないっぽい $wp_query = new WP_Query(); $param = array( 'post_type' => 'hoge', 'paged' => $paged ); $wp_query->query($param); if($wp_query->have_posts()): while($wp_query->have_posts()) : $wp_query->the_post(); ?> ここで記事をループさせる <?php endwhile; endif; ?> <?php if ($wp_query->max_num_pages > 1): // ここからページネーション echo '<div class="new-pagenation">'; echo paginate_links(array( 'base' => get_pagenum_link(1) . '%_%', 'format' => '?paged=%#%', 'current' => max(1, $paged), 'total' => $wp_query->max_num_pages, 'next_text' => '次へ', 'prev_text' => '前へ' )); echo '</div>'; endif; ?> |
paginate_links()というナイスな関数を使うのが肝で、パラメータでURLのフォーマットを設定することができる。他にもいろいろパラメータを設定できる優れもので、僕もこんな関数があることを初めて知りました。具体的な使用方法はWordPress Codexを参照してください。
次回以降普通のページネーションでもこれ使おう…
あとは、paginate_links()で出力されるhtmlに合わせ、スタイリングしてやりましょう。
以上、現場からでした。
これでも動かない場合は、こっちも見てみてね。
コメント
5年も前の記事にコメントしてもあれですが…
条件を「固定ページのとき」にしたいはずなので、
functions.php の 4行目は、
is_archive ではなく is_page(‘【固定ページのスラッグ】’) が正しいかと…
あと、フィルターフック系は関数を閉じる前に、return $redirect_url; を書いておかないと、なにも return しないパターンが生まれてしまうから間違っているかと…
本来やりたいことは
【固定ページで条件を満たすときにリダイレクトしない】
なはずが
【アーカイブページで条件を満たすときにリダイレクトしない、そして他のページでもリダイレクトしない】
というとんでもないコードになっているかと…