[WordPress]プラグイン不要!WP_Queryを使ったときのPageNaviの作り方

WP_Queryを使うとページナビが作れない?

どうしたものかと思案していたのですが、「Theme-checkプラグイン」にヒントがありました。

REQUIRED: The theme doesn’t have post pagination code in it. Use posts_nav_link() or paginate_links() or next_posts_link() and previous_posts_link() to add post pagination.

ページナビを追加するために「posts_nav_link()」「paginate_links()」「next_posts_link()」「previous_posts_link() 」の中のどれかを使いなさいというメッセージですね。

テストサイトで4つとも試した所、「paginate_links()」がWP_Queryでも使えるページナビに使えそうでした。

paginate_linksを設定する

例によって関数リファレンスのコードで色々試してみます。

関数リファレンス/paginate links – WordPress Codex 日本語版

<?php
global $wp_query;

$big = 999999999; // need an unlikely integer

echo paginate_links( array(
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $wp_query->max_num_pages
) );
?>

home.phpのような記事リストを表示させるページに追加すると、こんな感じになります。

Developer_Tools_-_http___hideokamoto_xsrv_jp__と_サイトタイトル__

navタグでマークアップすることで、簡単にページナビが設定できます。

WP_Queryを使用している場合の注意点

このpagenate_linkですが、実はWP_Queryを使用する場合、もう1工夫必要となります。

WP_Queryを以下のように設定している場合・・・

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

$args = array(
    'posts_per_page' => 5,
    'category_name' => 'gallery',
    'paged' => $paged,
);

$the_query = new WP_Query( $args );
?>

pagenate_linkのコードはこのようになります。

<?php
$big = 999999999; // need an unlikely integer

echo paginate_links( array(
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $the_query->max_num_pages
) );
?>

大事なことは、new WP_Queryを設定している変数(この場合「$the_query」)を、「total」内で呼び出すことです。

totalは「全体のページ数」を設定するパラメーターで、この設定をしないと「常にページナビが4ページで設定」されてしまいます。

あ

先ほどのサンプル。
3ページ分しか記事がなくても、4ページ目のリンクを表示する。

この設定を忘れると、2つのデメリットが発生します。

1:ソフト404エラーの発生

通常コンテンツが存在しないページへのアクセスには「404エラーページ」が表示されます。

しかしpagenate_linkのtotal設定を忘れると、「コンテンツが無いページ」が生成されてしまいます。

例えば「記事数30件、1ページあたり10件表示のブログなのに、31〜40件目を表示させるページが生成される」などですね。

この「コンテンツが存在しないが、404エラーを返さない現象」を「ソフト404エラー」とよびます。

存在しないページに対して 404 と 410 以外のコードを返すこと(または 404 を返す代わりにホームページなど他のページにリダイレクトすること)は、問題となる可能性があります。

引用元: ソフト 404 エラー – ウェブマスター ツール ヘルプ.

「ソフト404エラー」のデメリットについて、ウェブマスターツールのヘルプにはこのようにまとめられています。

まず、その URL にページが存在することが検索エンジンに明示されます。その結果、URL がクロールされ、コンテンツがインデックスに登録される場合があります。

存在しないページに対して Googlebot の時間が消費されるため、所有している固有の URL の検出が遅れたり、アクセスの頻度が少なくなったりする可能性があります。

また、サイトのクロール範囲にも影響する可能性があります(検索クエリ「ファイルが見つかりません」でサイトが上位にランクされることは避ける必要があります)。
引用元: ソフト 404 エラー – ウェブマスター ツール ヘルプ

SEOを重視するならば、ソフト404エラーは発生させないようにしたいものです。

2:過去記事へのアクセスが困難に

2つめは「5ページ目以降の記事にアクセスできなくなる」という問題です。

先ほどは「30記事しかないのに、40記事分のリストを出す」という問題でしたが、こちらは反対に「50記事あるのに、40記事分のリストを出す」という現象が発生します。

ブログ記事を書き続ける以上、アーカイブページからアクセスできない記事がある状況はやはり回避したいものです。

pagenate_linkのカスタマイズ方法

ページナビの表示方法をカスタマイズする方法として、様々なパラメーターがpagenate_linkには設定されています。

今回はその中でもよく使いそうなパラメーターを4つ紹介します。

1:「前へ」と「次へ」を変更するパラメーター

prev_text
(string) (任意) 前のページへ送る時のリンクの文言。’prev_next’ という引数を正しく設定しなければ動きません。
初期値: __(‘« Previous’)
next_text
(string) (任意) 次のページへ送る時のリンクの文言。’prev_next’という引数を正しく設定しなければ動きません。
初期値: __(‘Next »’)

コード・表示サンプル
サイトタイトル__ 4

<?php
$big = 999999999; // need an unlikely integer

echo paginate_links( array(
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
        'prev_text' => '<span>モドル</span>',
        'next_text' => '<span>ススム</span>',   
'total' => $wp_query->max_num_pages
) );
?>

2:ページ番号の前後に文字を表示するパラメーター

before_page_number
(string) (任意)ページ番号の前に表示する文字列。
after_page_number
(string) (任意)ページ番号の後に追加する文字列。

コード・表示サンプル
サイトタイトル__ 3

<?php
$big = 999999999; // need an unlikely integer

echo paginate_links( array(
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
        'before_page_number' => '<span>前に表示</span>',
        'after_page_number' => '<span>後ろに表示</span>', 
'total' => $the_query->max_num_pages
) );
?>

この他のカスタマイズ方法については、Codexをご覧下さい。

関数リファレンス/paginate links – WordPress Codex 日本語版

*「before_page_number」など、日本語版には紹介されていないパラメーターもあります。
 英語版も併せて確認されることをオススメします。

Function Reference/paginate links « WordPress Codex

query_postsからwp_queryへ

おおよそのWordPress本では、記事リストの取得に「query_posts」を使用する方法が紹介されています。

しかしCodexに次のような記述がされるなど、どうもあまりテーマの中で使って欲しいと思われていない気配があります。

query_postsを使うことによって、ページ上のメインクエリーが置き換えられ、ページの読み込み速度に影響を与えることに留意してください。最悪の場合、倍かそれ以上の処理が発生します。簡単に使える代わりに、この関数は混乱と問題を引き起こす傾向があります。下記の注意をご覧ください。

一般的な投稿の取得には、WP_Queryか、get_postsを使ってください。

引用元: テンプレートタグ/query posts – WordPress Codex 日本語版.

WP_Queryを使った場合のページナビの作り方は、ほとんどがプラグインベースの記事ばかりです。

ですが自力で作る方法を知っておくことも必要じゃないかなと思います。

Follow me!

[WordPress]プラグイン不要!WP_Queryを使ったときのPageNaviの作り方” に対して 2 件のコメントがあります

  1. より:

    こんにちは!
    記事を参考にさせて頂き、WP_Queryとpaginate_linksを使い記事のソート、ページネーションを実現させたいと思っておりますがページネーションのみうまくいきません。。。
    現在記事数は15で’posts_per_page’ => 5に設定しているのですが、ページネーションが5まで出てしまいます。
    そのため、global $wp_query;と’total’ => $wp_query->max_num_pagesを追記したのですが、
    今度はこの行「’total’ => $the_query->max_num_pages」でNotice: Trying to get property of non-objectが出てしまいました。
    原因がわからず困っております。
    もしお時間がありましたら教えて頂けると助かります。

  2. $the_queryの中にmax_num_pagesという値がないからではないかと。
    var_dump( $the_query );でデバッグしてみてください。