BBH
-Biz Branding Hub-
投稿日 : 
2019/08/22
更新日 : 
2019/08/22

プラグインを使わずに自前でWordPressでページャーを作る方法

WordPressでのブログサイトにはページャーが欠かせません。
こんな感じのパーツですね。

今回はページャーの実装方法について解説していきます。
ただ、こうしたページャーはプラグインなどでも実現可能ですので、特にこだわりが無ければそれらを導入した方が早いです。
自分で細かいカスタマイズをしたいという場合は、今回紹介するように自分で一から実装するといいでしょう。

ソースコード

index.php

<?php 
    // 現在ページを取得
    $cur_page = get_current_page();

    // 最大ページを取得
    if($pages == '') {
        global $wp_query;
        $pages = $wp_query->max_num_pages;
        if(!$pages)
        {
            $pages = 1;
        }
    }

    // Numericページネーションの範囲(現在記事の前後3ページ)
    $NUMERIC_PAGER_COUNT = 3;
    $numeric_start = $cur_page > $NUMERIC_PAGER_COUNT ? $cur_page - $NUMERIC_PAGER_COUNT : 1;
    $numeric_end   = $cur_page + $NUMERIC_PAGER_COUNT > $pages ?    // 現在ページ+ページネーション表示数が最大ページを超えたら
                        $pages : 
                        $cur_page + $NUMERIC_PAGER_COUNT;
?>

<nav class="ArticleList_PageNation">

    <?php // ==================== 前のX件 ====================?>
    <?php if($cur_page >= 2 && $pages >= 2) {?>
        <a href="<?php echo get_pagenum_link($cur_page - 1) ?>" class="ArticleList_PageNation_Prev">前の<?php echo get_option('posts_per_page'); ?>件</a>
    <?php } else {   // デザイン崩れ防止のためのダミー要素を表示する。 ?>
        <a class="ArticleList_PageNation_Prev ArticleList_PageNation_Blank"></a>
    <?php } ?>

    <?php // ==================== Numericページャー ====================?>
    <div class="ArticleList_PageNation_Num">

        <?php // ========== 1ページ目 ==========?>
        <?php if($numeric_start >= 2) {  // 現在ページが2ページ目以上の場合、1ページ目を表示する。 ?>
                <a href="<?php echo get_pagenum_link(1) ?>" class="ArticleList_PageNation_Num_A">1</a>
            <?php if($numeric_start >= 3) {  // 現在ページが3ページ目以上の場合、 ... を表示する。 ?>
                <span class="ArticleList_PageNation_Num_Omitted">...</span>
            <?php } ?>
        <?php } ?>


        <?php // ========== X~X+5ページ目 ==========?>
        <?php 
            // 現在のページを起点に前後3ページまでを表示する
            for ($i = $numeric_start; $i <= $numeric_end; $i++) {
                if($i === $cur_page) { // 現在ページの場合、非アクティブにする
        ?>
                    <span class="ArticleList_PageNation_Num_A_Crrent"><?php echo $i ?></span>
        <?php } else {  // それ以外は通常 ?>
                    <a href="<?php echo get_pagenum_link($i) ?>" class="ArticleList_PageNation_Num_A"><?php echo $i ?></a>
        <?php }} ?>

        <?php // ========== 最大ページ ==========?>
        <?php if($numeric_end < $pages) {  // 終了ページが最大ページ未満の場合、最終ページを表示する。 ?>
            <?php if($numeric_end < $pages - 1) {  // 終了ページが最大ページ - 1 よりも小さい時、 ... を表示する。 ?>
                <span class="ArticleList_PageNation_Num_Omitted">...</span>
            <?php } ?>
                <a href="<?php echo get_pagenum_link($pages) ?>" class="ArticleList_PageNation_Num_A"><?php echo $pages ?></a>
        <?php } ?>

    </div>

    <?php // ==================== 次のX件 ====================?>
    <?php if($cur_page < $pages) {?>
        <a href="<?php echo get_pagenum_link($cur_page + 1) ?>" class="ArticleList_PageNation_Next">次の<?php echo get_option('posts_per_page'); ?>件</a>
    <?php } else {   // デザイン崩れ防止のためのダミー要素を表示する。 ?>
        <a class="ArticleList_PageNation_Next ArticleList_PageNation_Blank"></a>
    <?php } ?>

</nav>

function.php

function get_current_page() {
  $current_pgae = get_query_var( 'paged' ); 
  $current_pgae = $current_pgae == 0 ? 1 : $current_pgae;
  return $current_pgae;
}

処理概要

ページャーに必要なパーツは大きく3つです。
「前へ」と「次へ」と「ページ番号」です。

現在のページと総ページ数からこれらの要素を動的に生成していきます。
では、詳細な処理内容についてみて行きましょう。

必要な情報を取得する

ページャーを生成するには、最低限「現在のページ」情報が必要です。
ページャーのデザインによっては、「最大ページ」や「表示するページ番号」も必要になってきます。

例えば、以下のように「... 最終ページ番号」のように表示する場合は、最大ページが必要になります。
最終ページが何ページ目なのかがわからないとページ番号を出せませんからね。

「表示するページ番号」はページ番号リンクを出すときに必要になります。
例えば、3ページ目から9ページ目の場合は、以下のように表示されます。

考え方的には現在のページから前後Xページを出す、のような考え方が基本になるかと思います。

今回のページャーでは、「現在のページ」、「最大ページ」、「表示するページ番号」を取得しています。

・現在のページ
現在ページは、get_current_page() で取得しています。
get_current_page() は、自作関数で処理の実体は、function.phpに記載しています。
get_query_var( 'paged' )で現在ページを取得しています。
ただし、この処理は1ページ目の場合0が返ってきてしまうので、以下の処理で0の時は1とみなすようにしています。
$current_pgae = $current_pgae == 0 ? 1 : $current_pgae;

・最大ページ
最大ページとは、ページングがいくつまであるかを表します。
例えば、100記事存在し、1ページに10記事表示するとします。
その場合、最大ページは100/10で10ページとなります。
端数は1ページとなりますので、101記事の場合は11ページとなります。(101/10 = 10あまり1なので)

前へリンク

前へリンクの生成は簡単です。
単純に現在ページ-1のリンクを生成すればいいです。
リンクを生成する際は、get_pagenum_link()という便利な関数が存在します。
引数にページ数を与えてやれば、そのページへの遷移リンクを生成してくれます。

「前のX件」のように出したい場合は、get_option('posts_per_page')を使うと良いです。
これを使用することで、WordPresで設定した1ページ当たりの表示記事数を取得することができます。
WordPres管理画面で「設定>表示設定>1ページに表示する最大投稿数」から設定できる項目ですね。

現在より前のページが無い場合は以下のように非表示にすればいいでしょう。

次へリンク

次へリンクも前へと同様で、現在ページ+1のリンクを生成してやればいいです。
こちらも同様に次のページが存在しない場合は、非表示にしましょう。
最大ページ<=現在ページの時は非表示にしてやればいいです。

ページ番号

「前へ」と「次へ」は簡単でしたが、「ページ番号」は少しロジックが複雑になります。
特に表示の仕方にこだわればこだわるほどロジックが難解になっていくので、ある程度のところで妥協するのも大事です。
ページャーは仕様によって中身の実装が異なるので、今回は当サイトで使用しているページャーを例に実装方法を解説していきます。

当サイトのページャーは、
・現在ページから前後3ページ目までを出す
・現在ページはデザインを変更してわかるようにする
・1ページ目と最終ページは常に出す
・前後3ページに1ページ目と最終ページが含まれない、隣接しない場合は「...」で省略を表す

説明としてわかりやすいように実際のロジックとは少し順番を変えて説明していきます。
まずは、「現在ページから前後3ページ目までを出す」を見ていきましょう。
これは、例えば現在ページが6ページなら、3~5ページ、7~9ページを出すということです。

ただし、前後3ページが無い場合も考慮しないといけません。
例えば、現在ページが2ページ目の場合は、3つ前のページは0ページなので存在しません。

このあたりの制御は最初の情報設定のロジックで行っています。

sidebar.php

// Numericページネーションの範囲(現在記事の前後3ページ)
$NUMERIC_PAGER_COUNT = 3;
$numeric_start = $cur_page > $NUMERIC_PAGER_COUNT ? $cur_page - $NUMERIC_PAGER_COUNT : 1;
$numeric_end   = $cur_page + $NUMERIC_PAGER_COUNT > $pages ?    // 現在ページ+ページネーション表示数が最大ページを超えたら
                    $pages : 
                    $cur_page + $NUMERIC_PAGER_COUNT;

NUMERIC_PAGER_COUNTが前後何ページを表示するかの設定値になります。
numeric_startがページ番号の最初で、numeric_endが最後を表します。
現在ページがNUMERIC_PAGER_COUNTよりも大きい場合は、「現在ページ - NUMERIC_PAGER_COUNT」となります。
現在ページが4ページの場合は、startが「4 - 3 = 1」となるわけですね。
ただし、現在ページがNUMERIC_PAGER_COUNTより小さい場合、つまり「現在ページ - NUMERIC_PAGER_COUNT」がマイナスになる場合は、1とします。
最終ページも同じで基本は+3を出しますが、+3した結果、最大ページを上回ってしまったら、最大ページを設定します。

ここが決まれば後は、ループでリンクを生成するだけです。
以下の部分のロジックですね。

sidebar.php

<?php // ========== X~X+5ページ目 ==========?>
<?php 
    // 現在のページを起点に前後3ページまでを表示する
    for ($i = $numeric_start; $i <= $numeric_end; $i++) {
        if($i === $cur_page) { // 現在ページの場合、非アクティブにする
?>
            <span class="ArticleList_PageNation_Num_A_Crrent"><?php echo $i ?></span>
<?php } else {  // それ以外は通常 ?>
            <a href="<?php echo get_pagenum_link($i) ?>" class="ArticleList_PageNation_Num_A"><?php echo $i ?></a>
<?php }} ?>

この時に、現在ページの場合はそのことがわかるようにCSSのクラスを付け替えています。

次に「1ページ目と最終ページは常に出す」です。
これは、「前後3ページに1ページ目と最終ページが含まれない、隣接しない場合は「...」で省略を表す」との兼ね合いで少し複雑になっています。
1ページ目を常に出すのはいいのですが、開始ページが1ページ目または2ページ目か3ページ目以降かで「...」を出すかどうかの判定が必要になります。
なので、開始ページが1ページ目または2ページ目であれば、「X~X+5ページ目」で処理し、3ページ目以降であれば、1ページ目と「...」を出すようにしています。
最終ページも同様で、最終ページに最大ページと最大ページ-1が含まれていなければ「...」を出すようにしています。

Profile

管理人プロフィール

都内でITエンジニアをやってます。
変遷:中規模SES→独立系SIer→Webサービス内製開発
使用技術はその時々でバラバラですが、C#、AWSが長いです。
どちらかと言うとバックエンドより開発が多かったです。
顧客との折衝や要件定義、マネジメント(10名弱程度)の経験あり。
最近はJava+SpringBootがメイン。

Recommend