カスタマイズしやすくコピペでもOKなレスポンシブ対応ページ送り:改善版|WP_Query対応【WordPress】

以前の記事で「レスポンシブでカスタマイズしやすいページ送り」を紹介しましたが、これは基本的に archive.php や category.php 等のアーカイブテンプレートでの使用が前提となっており、固定ページで new WP_Query を使用した投稿一覧のページ送りには対応していませんでした。

特別な理由がなければアーカイブテンプレートを使うほうが確実でおすすめですが、
今回は 固定ページでの new WP_Query でも動作するよう修正したものを紹介します。

とりあえず設置したいという場合は「ページ送りの設置」の章からご覧ください。

WP_Query で動かない原因

合計ページ数が取得できていない

当サイトで紹介したもののほか、多くのページ送りはglobal $wp_queryのようにグローバル変数を読み込み、そこから取得可能な “合計ページ数” を利用してページ送り処理を行っています。

しかしnew WP_Query()を使って任意のインスタンス名を付けたループの場合、グローバル変数では “合計ページ数” が取得できないためページ送りが動作しなくなります。

例えば次のようにnew WP_Query()を使って$wp_query以外のインスタンス名を付けた場合、ページ送り関数内でglobal $wp_queryを読み込んでも合計ページ数は取得できません。

$the_query = new WP_Query()
$my_query = new WP_Query()
$q = new WP_Query()

合計ページ数を取得するにはそれぞれのインスタンス名$the_query$my_query$qを参照する必要があります。

ページ送りパラメータの不足

ページ送りを行うためにはnew WP_Query()のパラメータ'paged'が必須となります。
これにより現在のページ番号を利用した処理が可能になります。

ページ送りは表示されるものの、1ページ目しか表示できない場合はこれが原因かもしれません。

ページ送りの設置

functions.php にページ送り関数を定義

ページ送りの関数をfunctions.phpに貼り付けます。
3~7行目は表示に関する簡単な設定を行います。

11行目:インスタンス名を受け取っている場合はそれを参照します。
16行目:三項演算子で現在のページ番号を取得します。

function my_paginate( $query_name = '' ) {
	$settings = array(
		'side_range' => 3,    // 現在ページの左右の表示数.
		'txt_prev'   => '<',  // 一つ戻るテキスト.
		'txt_next'   => '>',  // 一つ進むテキスト.
		'txt_first'  => '<<', // 最初へ移動テキスト.
		'txt_last'   => '>>', // 最後へ移動テキスト.
	);

	if ( '' !== $query_name ) {
		$query = $query_name;
	} else {
		global $paged, $wp_query;
		$query = $wp_query;
	}
	$paged     = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
	$showitems = ( $settings['side_range'] * 2 ) + 1;
	$pages     = $query->max_num_pages;

	if ( 1 !== $pages ) {
		echo "<div class=\"pagination\">\n";
		echo "  <ul class=\"pagination__list\">\n";
		for ( $i = 1; $i <= $pages; $i++ ) {
			if ( 1 !== $pages && ( ! ( $i >= $paged + $settings['side_range'] + 1 || $i <= $paged - $settings['side_range'] - 1 ) || $pages <= $showitems ) ) {
				echo ( $paged === $i ) ?
				'    <li class="pagination__item--current">' . esc_html( $i ) . "</li>\n" :
				'    <li class="pagination__item"><a href="' . esc_url( get_pagenum_link( $i ) ) . '">' . esc_html( $i ) . "</a></li>\n";
			}
		}
		echo "  </ul>\n";
		echo '  <p class="pagination__pos">Page ' . esc_html( $paged ) . '/' . esc_html( $pages ) . "</p>\n";
		if ( $paged > 2 && $paged > $settings['side_range'] + 1 && $showitems < $pages ) {
			echo '  <a class="pagination__btn--first" href="' . esc_url( get_pagenum_link( 1 ) ) . '">' . esc_html( $settings['txt_first'] ) . "</a>\n";
		}
		if ( $paged > 1 ) {
			echo '  <a class="pagination__btn--prev" href="' . esc_url( get_pagenum_link( $paged - 1 ) ) . '">' . esc_html( $settings['txt_prev'] ) . "</a>\n";
		}
		if ( $paged < $pages ) {
			echo '  <a class="pagination__btn--next" href="' . esc_url( get_pagenum_link( $paged + 1 ) ) . '">' . esc_html( $settings['txt_next'] ) . "</a>\n";
		}
		if ( $paged < $pages - 1 && $paged + $settings['side_range'] - 1 < $pages && $showitems < $pages ) {
			echo '  <a class="pagination__btn--last" href="' . esc_url( get_pagenum_link( $pages ) ) . '">' . esc_html( $settings['txt_last'] ) . "</a>\n";
		}
		echo "</div>\n";
	}
}

冒頭で紹介した動かない原因に対し、テンプレート側からWP_Query()のインスタンス名を渡した場合の処理を追加することで解決しています。

参考リンク
WordPress Codex – WP_Query
WordPress Codex – wp_reset_postdata()

表示するテンプレートファイルを編集

ページネーションを表示するテンプレートファイルの種類に応じて次のように関数を呼び出します。

アーカイブテンプレートにページ送りを表示する場合

archive.php や category.php 等のアーカイブテンプレートにページ送りを表示したい場合は次のように書きます。

my_paginate();

固定ページで WP_Query() による投稿一覧のページ送りを表示する場合

WP_Query()によるループを設定します。
パラメータ'paged' => $pagedを忘れないようにしてください。

<?php
$my_query = new WP_Query( // ここで命名したインスタンス名を20行目で使用
	array(
		'post_type'      => 'post',
		'paged'          => $paged, // ページ送りを行うために必須
		'posts_per_page' => 10,
	)
);

if ( $my_query->have_posts() ) :
	echo '<ul>';
	while ( $my_query->have_posts() ) :
		$my_query->the_post();
		?>
	<li><a href="<?php the_permalink(); ?>"><?php the_title_attribute(); ?></a></li>
		<?php
	endwhile;
	echo '</ul>';

	my_paginate( $my_query ); // インスタンス名を引数に指定
	wp_reset_postdata();
endif;
?>

20行目:WP_Queryで生成したインスタンス名$my_queryを引数としてページ送り関数へ渡します。
21行目:グローバル変数であるthe_post()が変更されているため、wp_reset_postdata()でリセットします。

ページ送りの動作確認

正しく設置できていれば次のような構造のHTMLが書き出されます。

<div class="pagination">
	<ul class="pagination__list">
		<li class="pagination__item"><a href="">1</a></li>
		<li class="pagination__item"><a href="">2</a></li>
		<li class="pagination__item--current">3</li>
		<li class="pagination__item"><a href="">4</a></li>
		<li class="pagination__item"><a href="">5</a></li>
		<li class="pagination__item"><a href="">6</a></li>
	</ul>
	<p class="pagination__pos">Page 3/6</p>
	<a class="pagination__btn--first" href="">&lt;&lt;</a>
	<a class="pagination__btn--prev" href="">&lt;</a>
	<a class="pagination__btn--next" href="">&gt;</a>
	<a class="pagination__btn--last" href="">&gt;&gt;</a>
</div>

CSSで装飾される前の状態では次のようなページネーションが表示されます。
(既存のCSSの影響で見た目が異なる場合があります。)
ここからCSSで見栄えを整えていきます。

CSSデザインサンプル(22.02.24追記)

CSSによるデザインカスタマイズ

次のページにCSSによるデザインサンプルを置いています。
この記事で紹介したページネーションに対応しており、コピペするだけで使えるようになっています。

タイトルとURLをコピーしました