SP用メニューボタン
ソレゾレブログ

技術的な事だったり日常の気になる事だったり

WordPress過去投稿(アーカイブ)の月毎表示にページ送りを付ける方法

スポンサーリンク

WordPressには、同じカテゴリに属する前もしくは後の投稿を取得してきてくれるページ送り関数(get_previous_post、get_next_post)が用意されていますが、例えば月毎のような過去のアーカイブを一覧表示した場合、次の月や前の月のアーカイブ一覧を表示してくれるようなページ送り機能はありません。

そこで、それを自作してみようと調べた結果を残します。

どんな方法を使ったか

標準で用意されている関数にはやりたいことを満たす関数が無かったため、投稿が記録されているWPDBのテーブル(wp_posts)を参照して、現在表示している月の一つ前の投稿から年月を取得し、その年月をget_month_linkのオプションに指定してリンクを生成する方法を使いました。

スポンサーリンク

ソースコード

ソースコードは下記です。

<nav class="single-pagination">
    <ul class="container">
        <li class="prev">
            <?php $prev_result = my_get_custom_archive_month('prev'); ?>
            <?php if ( $prev_result <> "" ) { ?>
                <a href="<?php echo my_get_custom_archive_month('prev'); ?>">前へ</a>
            <?php } ?>
        </li>
        <li class="return">
        </li>
        <li class="next">
            <?php $next_result = my_get_custom_archive_month('next'); ?>
            <?php if ( $next_result <> "" ) { ?>
                <a href="<?php echo my_get_custom_archive_month('next'); ?>">次へ</a>
            <?php } ?>
        </li>
    </ul>
</nav>
function my_get_custom_archive_month ( $args ){

    $link_next_month = '';
    $link_prev_month = '';
    $thisyear = intval( get_the_time( 'Y' ) );
    $thismonth = intval( get_the_time( 'm' ) );

    global $wpdb;

    if ( $args == 'prev' ) {
        $previous = $wpdb->get_row(
            "SELECT DISTINCT MONTH(post_date) AS month, YEAR(post_date) AS year
            FROM $wpdb->posts
            WHERE post_date < '$thisyear-$thismonth-01'
                AND post_status = 'publish'
                AND post_type = 'my_posts'
                ORDER BY YEAR(post_date) DESC , MONTH(post_date) DESC LIMIT 1"
        );
        if( $previous ) $result = get_month_link( $previous->year, $previous->month ) . '?post_type=my_posts';
        return $result;
    } elseif ( $args == 'next' ) {
        $next = $wpdb->get_row(
            "SELECT DISTINCT MONTH(post_date) AS month, YEAR(post_date) AS year
            FROM $wpdb->posts
            WHERE post_date > '$thisyear-$thismonth-01'
                AND MONTH( post_date ) != MONTH( '$thisyear-$thismonth-01' )
                AND post_status = 'publish'
                AND post_type = 'my_posts'
                ORDER BY YEAR(post_date) ASC , MONTH(post_date) ASC LIMIT 1"
        );
        if( $next ) $result = get_month_link( $next->year, $next->month ) . '?post_type=my_posts';
        return $result;
    }
}

ソースコードの説明

変数宣言

    \\次のアーカイブ一覧ページのURL
    $link_next_month = '';

    \\前のアーカイブ一覧ページの URL
    $link_prev_month = '';
 
    \\現在表示されているアーカイブ一覧ページの年を取得
    $thisyear = intval( get_the_time( 'Y' ) );

    \\現在表示されているアーカイブ一覧ページの月を取得
    $thismonth = intval( get_the_time( 'm' ) );

「次のアーカイブ一覧ページのURL」「前のアーカイブ一覧ページの URL」を格納する変数と、「現在表示されているアーカイブ一覧ページの年」「 現在表示されているアーカイブ一覧ページの月」を取得して格納します。

WordPressのDBとやり取りできるようにする

   global $wpdb;

WordPressのデータべースを操作できるようにするため、wpdbクラスをグローバル変数として宣言します。

「前へ」リンクをクリックしたときにページ送りリンク生成関数を実行

        <li class="prev">

      //my_get_custom_archive_month関数を実行し$prev_resultに格納
            <?php $prev_result = my_get_custom_archive_month('prev'); ?>

「前へ」のリンクをクリックしたら、「my_get_custom_archive_month」関数が実行されます。その時に引数として「prev」が渡されます。

function my_get_custom_archive_month ( $args ){
     :
     :

    if ( $args == 'prev' ) {

        //wpdbから指定条件のテーブルを取得して$previousに確認(条件はSELECT文で第一引数に書く)
        $previous = $wpdb->get_row(

       //見つかったテーブルのpost_dateから年月だけを表示
            "SELECT DISTINCT MONTH(post_date) AS month, YEAR(post_date) AS year

            //wp_postsテーブルから取得
            FROM $wpdb->posts 
      
            //今月1日より前の日付で絞る
            WHERE post_date < '$thisyear-$thismonth-01'

         //公開済みの投稿で絞る
                AND post_status = 'publish'

         //私はカスタム投稿(my_posts)を使っていたので絞った。
                AND post_type = 'my_posts'

         //年月を降順で取得し、降順で初めに見つかった1行だけ取得。
                ORDER BY YEAR(post_date) DESC , MONTH(post_date) DESC LIMIT 1");

    //$previousに直近過去の投稿の年月が入っていたら直近過去年月のアーカイブページへのリンクURLを生成し、関数の実行結果として返す
        if( $previous ) $result = get_month_link( $previous->year, $previous->month ) . '?post_type=my_posts';
        return $result;

渡された引数の「prev」は「my_get_custom_archive_month」関数の$argsに格納され、if文の条件として使われます。

$wpdb->get_rowによってwpdbからテーブルを取得してきます。

$wpdb->get_rowの第一引数に抽出条件を指定しています。

投稿はwp_postsテーブルに格納されているので、FROMでwp_postsテーブルのみ表示させています。

wp_postsテーブルにはすべての投稿が記録されているので、WHEREで条件を絞っています。今回は下記条件で絞っています。

  • 公開済みの投稿である(publish)
  • カスタム投稿my_postsの投稿である(私がカスタム投稿を使っているので)
  • この条件にヒットしたものを降順で表示して、降順で一番目に見つかったものの年月を取得

SELECTに取得したテーブルの年月のみを返すオプションを付け、取得したテーブルの年月だけを返します。

結果、現在表示している年月アーカブページより古い投稿があった場合は、$previousにそのテーブルの年月が格納されます。

HTMLコードの生成

      //$prev_resultが空じゃなかったら(前の月のアーカイブがあったら)リンクを表示
            <?php if ( $prev_result <> "" ) { ?>
                <a href="<?php echo my_get_custom_archive_month('prev'); ?>">前へ</a>
            <?php } ?>
        </li>

現在表示している年月のアーカブページより古い投稿ページがあった場合だけ、「前へ」のリンクを生成しています。

「次へ」のリンク

「次へ」 のリンクをクリックしたときも、「前へ」のリンクをクリックしたときと処理は同じです。

    } elseif ( $args == 'next' ) {
        $next = $wpdb->get_row(
            "SELECT DISTINCT MONTH(post_date) AS month, YEAR(post_date) AS year
            FROM $wpdb->posts
            WHERE post_date > '$thisyear-$thismonth-01'
                AND MONTH( post_date ) != MONTH( '$thisyear-$thismonth-01' )
                AND post_status = 'publish'
                AND post_type = 'my_posts'
                ORDER BY YEAR(post_date) ASC , MONTH(post_date) ASC LIMIT 1"
        );
        if( $next ) $result = get_month_link( $next->year, $next->month ) . '?post_type=my_posts';
        return $result;
    }