ここ最近は雨が続いていたのが、ようやく晴れて、春の陽気にぽかぽかしている金沢です。
当ブログも件数が増えてきました。10件ごとにページで分けておりますが、その際に使用したWordPressのテンプレート関数「the_posts_pagination」の説明と、テーマに合わせて編集したときの小ワザを紹介させていただきたいと思います。
なぜページネーションが必要なのでしょうか
WordPressの話に入る前に、ページネーションの話を少しさせて頂きます。ページネーションとは、アーカイブなど記事の一覧を表示するときに全件一気に表示させずに、ページで分けて小出しにすることです。ページング、ページャーとも言います。
ページネーションが必要となるのは、主に一覧の読み込みの軽減を必要とするときです。例えば記事の件数が100件くらいあるのにページネーションが無い場合は、サーバー側の処理が重くなりますし、サムネイル付であれば通信量も膨大になりますし、ページの読み込みが完了するまでの時間がとても長くなってしまいます。そのような応答の悪さはユーザーに好まれないだけでなく、SEO的な評価にもあまりよろしくないようです。
ページ番号を振り分けるのにとっても便利な「the_posts_pagination」
WordPressのバージョン4.1以降では、アーカイブページで利用可能なテンプレート関数の中にページネーションを出力する「the_posts_pagination」があります。以前は、URLパラメータを「$_GET」で取得して、「WP_Query」からページネーションを自力で作成するなんてことをしていましたが、とても苦戦していました。こちらの「the_posts_pagination」を使ったほうが極めて簡単です。
まず、「the_posts_pagination」をそのまま呼び出すと、下記のようなHTMLを出力します。
<nav class="navigation pagination" role="navigation"> <h2 class="screen-reader-text">投稿ナビゲーション</h2> <div class="nav-links"> <a class="prev page-numbers" href="http://www.online-inc.jp/archives/author/kanazawa">前へ</a> <a class="page-numbers" href="http://www.online-inc.jp/archives/author/kanazawa/">1</a> <span class="page-numbers current">2</span> <a class="page-numbers" href="http://www.online-inc.jp/archives/author/kanazawa/page/3">3</a> <span class="page-numbers dots">…</span> <a class="page-numbers" href="http://www.online-inc.jp/archives/author/kanazawa/page/5">5</a> <a class="next page-numbers" href="http://www.online-inc.jp/archives/author/kanazawa/page/5">次へ</a> </div> </nav>
説明しやすくするために現状のサイトよりもページ数が多いですが、 全5ページ中の2ページ目にいる状態です。こちらがデフォルトで使用した状態です。「the_posts_pagination」を呼び出す際に、連想配列の引数を指定することで出力をカスタマイズできます。デフォルトでセットされていたパラメータは下記の通りです。
array( 'mid_size' => 1, 'prev_text' => _x( 'Previous', 'previous post' ), 'next_text' => _x( 'Next', 'next post' ), 'screen_reader_text' => __( 'Posts navigation' ), )
「mid_size」は現在のページから前後何ページまでを表示させるかを指定するパラメータです。上記の出力例では2ページ目にいる状態ですので、前後1ページの「1」と「3」が出力され、「4」が省略されています。最初と最後のページは常に出力されますので、「1 2 3 … 5」となったということです。
「prev_text」と「next_text」は、「前へ」と「次へ」の表示テキストです。「_x」や「__」は翻訳関数ですので、日本語に変換されています。同様に、「screen_reader_text」はh2の見出しタグのテキスト、上記の例では「投稿ナビゲーション」にあたるテキストのカスタマイズです。
このほかにもパラメータは存在し、下記のサイトが参考になります。
WordPressにページネーションを入れる方法 – Young Flavor
「the_posts_pagination」の中身を調査してみました
ここからが本題です。「the_posts_pagination」はある程度のカスタマイズはできるのですが、HTMLの構造自体を変更することはできないようです。「h2をh3に変更したい」とか「h2タグを取り除きたい」といったカスタマイズは、通常ではできないことが下記の調査結果からわかりました。「the_posts_pagination」の中身を見てみると、「get_the_posts_pagination」という関数を出力しているだけでしたので、「get_the_posts_pagination」のソースを確かめてみました。ソースの場所は「wp-includes/link-template.php」の2306行目でした。
function get_the_posts_pagination( $args = array() ) { $navigation = ''; // Don't print empty markup if there's only one page. if ( $GLOBALS['wp_query']->max_num_pages > 1 ) { $args = wp_parse_args( $args, array( 'mid_size' => 1, 'prev_text' => _x( 'Previous', 'previous post' ), 'next_text' => _x( 'Next', 'next post' ), 'screen_reader_text' => __( 'Posts navigation' ), ) ); // Make sure we get a string back. Plain is the next best thing. if ( isset( $args['type'] ) && 'array' == $args['type'] ) { $args['type'] = 'plain'; } // Set up paginated links. $links = paginate_links( $args ); if ( $links ) { $navigation = _navigation_markup( $links, 'pagination', $args['screen_reader_text'] ); } } return $navigation; }
この中の「_navigaion_markup」という関数が同ファイルの2358行目にあり、HTMLの文字列がありました。
function _navigation_markup( $links, $class = 'posts-navigation', $screen_reader_text = '' ) { if ( empty( $screen_reader_text ) ) { $screen_reader_text = __( 'Posts navigation' ); } $template = ' <nav class="navigation %1$s" role="navigation"> <h2 class="screen-reader-text">%2$s</h2> <div class="nav-links">%3$s</div> </nav>'; return sprintf( $template, sanitize_html_class( $class ), esc_html( $screen_reader_text ), $links ); }
こちらを見るかぎり、h2タグ自体はフィルターフックなどでも編集はできないことがわかります。これらのファイルを書き換えるのはアップデートなどの観点からあまりよろしくないので、次のような方法を行いました。
テンプレート関数を別名でコピーしてみました
テンプレート関数をfunctions.phpにコピーして関数名を変更することで、同じ機能をもつ関数を自由に編集することができます。例として、「the_posts_pagination」の見出しタグをh3に変更する場合は下記のようなコードになります。
function online_the_posts_pagination( $args = array() ) { $navigation = ''; // Don't print empty markup if there's only one page. if ( $GLOBALS['wp_query']->max_num_pages > 1 ) { $args = wp_parse_args( $args, array( 'mid_size' => 1, 'prev_text' => _x( 'Previous', 'previous post' ), 'next_text' => _x( 'Next', 'next post' ), 'screen_reader_text' => __( 'Posts navigation' ), ) ); // Make sure we get a string back. Plain is the next best thing. if ( isset( $args['type'] ) && 'array' == $args['type'] ) { $args['type'] = 'plain'; } // Set up paginated links. $links = paginate_links( $args ); if ( $links ) { $navigation = _online_navigation_markup( $links, 'pagination', $args['screen_reader_text'] ); } } echo $navigation; } function _online_navigation_markup( $links, $class = 'posts-navigation', $screen_reader_text = '' ) { if ( empty( $screen_reader_text ) ) { $screen_reader_text = __( 'Posts navigation' ); } $template = ' <nav class="navigation %1$s" role="navigation"> <h3 class="screen-reader-text">%2$s</h3> <div class="nav-links">%3$s</div> </nav>'; return sprintf( $template, sanitize_html_class( $class ), esc_html( $screen_reader_text ), $links ); }
「online_the_posts_pagination」は「get_the_posts_pagination」をもとに作成した関数です。「_navigation_markup」を呼び出すところを「_online_navigation_markup」を呼び出すように変更しています。また、入手用の関数と出力用の関数を分ける必要がありませんでしたので、最後の「return」を「echo」に変更しています。そして、「_online_navigation_markup」は、「_navigation_markup」のh2をh3に書き換えた関数です。
さらに、見出しタグを取り除いて、2つの関数を1つにまとめてしまった例が次のコードになります。
function online_the_posts_pagination( $args = array() ) { $navigation = ''; // Don't print empty markup if there's only one page. if ( $GLOBALS['wp_query']->max_num_pages > 1 ) { $args = wp_parse_args( $args, array( 'mid_size' => 1, 'prev_text' => _x( 'Previous', 'previous post' ), 'next_text' => _x( 'Next', 'next post' ), ) ); // Make sure we get a string back. Plain is the next best thing. if ( isset( $args['type'] ) && 'array' == $args['type'] ) { $args['type'] = 'plain'; } // Set up paginated links. $links = paginate_links( $args ); if ( $links ) { $template = ' <nav class="navigation pagination" role="navigation"> <div class="nav-links">%1$s</div> </nav>'; $navigation = sprintf( $template, $links ); } } echo $navigation; }
引数のパラメータ「screen_reader_text」の処理を省略できますので、こんなに短くまとめることができました。さらにデフォルトのパラメータも変えてしまえば、テンプレートファイルでの呼び出し時に引数の指定も省略できます。
いかがでしたでしょうか。こちらの方法は、他のWordPressのテンプレート関数にも応用できます。関数の中身を調べることが手間なときもありますが、WordPressのコアファイルの中にはPHPのテクニックとして非常に参考になるところもあります。芸は真似しろともいいますので、今後もコピー&ペーストに励みたいと思います。
金沢