Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【WordPress】先頭固定表示に対応してページネーション(ページャ)も表示する

More than 1 year has passed since last update.

やりたいこと

  • カテゴリアーカイブページで記事一覧を表示したい
  • 「ブログのトップに固定」にチェックした記事を先頭に固定表示したい
  • ページネーションも表示したい
  • 1ページ目の記事一覧では、先頭固定記事の数も含めた一覧を表示したい(要するにページ送りしても全て同じ件数表示)

コード

  • ページネーションは functions.phpwp_pagination() 関数を定義していますが、まとめて記述するかはご自由にどうぞ。
  • 1ページ目は、最初に先頭固定の記事一覧を表示して、残りの記事一覧を表示しています。要するにバラバラに表示しています。
  • 1ページ目だけ先頭に固定した記事の数を引いた一覧を表示しています。
  • サンプルコードでは 1 ページに MAX 9 件(コード上では AFTER_PAGE_DISPLAY_COUNT の数)の記事一覧を表示します。
  • 先頭固定する記事の数が 1 ページあたりの MAX 件数を超える想定はしていません。
category.php(記事のタイトルをリスト表示する例)
    <ol>
    <?php

    /**
     * 先頭固定を表示
     */
    // 現在のページ番号を取得
    $paged = get_query_var( 'paged', 1 );

    // 先頭固定したブログIDを格納する変数
    $post__not_in = [];

    // WP_Query() の引数には 'category_name'  => 'カテゴリのスラッグ名' でカテゴリを指定することが可能
    // $query_string はカテゴリアーカイブの場合、"category_name = カテゴリのスラッグ名" の文字列を返す
    // 文字列を処理して "category_name" => "カテゴリのスラッグ名" のように配列にして $org_args に代入
    parse_str ( $query_string, $org_args );

    // WP_Query() の引数に渡す条件を配列で格納
    $add_args = [
        'post_type'      => 'post',
        'posts_per_page' => -1,     // すべての投稿を含める
        'post__in'       => get_option( 'sticky_posts' )
    ];

    // array_merge で配列を結合
    $args = array_merge( $org_args, $add_args );

    // 記事データを $first_query に代入
    $first_query = new WP_Query( $args );

    if ( $first_query->have_posts() ) {
        while ($first_query->have_posts()) {
            $first_query->the_post();

            // 先頭固定表示したブログIDを $post__not_in に格納
            $post__not_in[] = $post->ID;

            if ($paged === 0) {
                // 表示する内容
                the_title( '<li>', '</li>');
            }
        }
    }

    /**
     * 先頭固定以外を表示
     */

    // 2ページ目以降の表示件数(この数は環境にあわせて適宜変更)
    define('AFTER_PAGE_DISPLAY_COUNT', 9);

    // 1ページ目の表示件数
    // $post__not_in には固定表示したブログIDが配列で格納されている
    // 2ページ目以降の表示件数から固定表示の数を引いた数を値として指定
    define('FIRST_PAGE_DISPLAY_COUNT', AFTER_PAGE_DISPLAY_COUNT - count($post__not_in));

    // 2ページ目なら AFTER_PAGE_DISPLAY_COUNT を数を、1ページ目なら FIRST_PAGE_DISPLAY_COUNT の数を $posts_per_page に代入
    $posts_per_page = $paged > 1 ? AFTER_PAGE_DISPLAY_COUNT : FIRST_PAGE_DISPLAY_COUNT;

    // WP_Query() の引数に渡す条件を配列で格納
    // post__not_in で先頭固定表示したブログIDを除外
    $add_args = [
        'post_type'      => 'post',
        'paged'          => $paged,
        'post__not_in'   => $post__not_in,
        'posts_per_page' => $posts_per_page
    ];

    // 2ページ目以降のオフセットを計算
    // オフセットは読み飛ばす投稿の数
    // 2ページ目の場合なら FIRST_PAGE_DISPLAY_COUNT の数を飛ばして、その次から一覧を表示する
    if ( $paged > 1 ) {
        $add_args['offset'] = FIRST_PAGE_DISPLAY_COUNT + ( $paged - 2 ) * AFTER_PAGE_DISPLAY_COUNT;
    }

    // array_merge で配列を結合
    $args = array_merge( $org_args, $add_args );

    // 記事データを $wp_query に代入
    $wp_query = new WP_Query( $args );

    // 合計ページ数を計算
    $wp_query->max_num_pages = ceil ( ( $wp_query->found_posts + (AFTER_PAGE_DISPLAY_COUNT - FIRST_PAGE_DISPLAY_COUNT) ) / AFTER_PAGE_DISPLAY_COUNT );

    if ( $wp_query->have_posts() ) {
        while ( $wp_query->have_posts() ) {
            $wp_query->the_post();

            // 表示する内容
            the_title( '<li>', '</li>');
        }
        wp_reset_postdata();
    }

    // ページネーション
    wp_pagination();
    ?>
    </ol>
functions.php
/**
 * ページネーション
 */
function wp_pagination() {
    global $wp_query;
    $big = 99999999;
    $page_format = 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,
        'prev_next'    => True,
        'prev_text'    => __('&lt;'),
        'next_text'    => __('&gt;'),
        'type'  => 'array'
    ) );
    if( is_array($page_format) ) {
        echo '<div class="pager"><ul class="pager_list">';
        foreach ( $page_format as $page ) {
            echo "<li class='pager_item'>$page</li>";
        }
    } else {
        echo '<div class="pager"><ul class="pager_list"><li class="pager_item current"><span class="current">1</span></li></ul></div>';
    }
    echo '</ul></div>';
    wp_reset_query();
}

感想

「ブログのトップに固定」は標準機能なので、もっと簡単に一覧を作れると思ってたけど、そんなことなかった...(1日消えた)

補足

先頭固定表示の記事だけに CSS クラスを追加する post_class()や、先頭固定表示か判定する is_sticky() などがあります。

参考サイト

4cres
せっせと駄文を量産してます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away