レスポンシブなページ送りの設置|WP_Queryにも対応【WordPress】

archive.php や category.php 等のアーカイブテンプレートのほか、固定ページで new WP_Query を使用した投稿一覧にも使用可能なページ送りを設置します。

設置したページ送りの見栄えを整えるためのCSSデザインサンプルも用意しています。

このページ送りの特徴

  • 表示名を変更可能な「最初へ・前へ・次へ・最後へ」ボタン。
  • 「現在ページ番号 / 全ページ数」を表示。
  • ページ番号リンクの表示数を変更可能。
  • 上記項目の表示を切り替えてレスポンシブ対応。
  • サンプルをコピペするだけでも使える。
  • BEMによる命名規則に則ったクラス名を出力。

CSSが適用されていない状態では「ページ番号・現在ページ数・移動ボタン(最初へ・前へ・次へ・最後へ)」の全てが表示されますが、CSSメディアクエリを利用して要素の表示/非表示やレイアウトを調整するレスポンシブデザインとなっています。

ページ送りの設置

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";
	}
}

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

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

ページネーションを表示するテンプレートファイルの種類に応じてどちらかの方法で関数を呼び出します。

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

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

my_paginate();

方法2. 固定ページで 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デザインサンプル

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

ページ送りが 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を参照する必要があります。

今回紹介したページネーションでは、テンプレート側からWP_Query()のインスタンス名を渡した場合の処理を追加することで解決しています。

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

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

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


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