やりたいこと
- カテゴリアーカイブページで記事一覧を表示したい
- 「ブログのトップに固定」にチェックした記事を先頭に固定表示したい
- ページネーションも表示したい
- 1ページ目の記事一覧では、先頭固定記事の数も含めた一覧を表示したい(要するにページ送りしても全て同じ件数表示)
コード
- ページネーションは
functions.php
にwp_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' => __('<'),
'next_text' => __('>'),
'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()
などがあります。