前回の続きです。
今回は「pagination」をやります。
日本語的には「ページ割」とか「ページ付」という感じになるようです。
要するに、投稿一覧を複数ページに分けて表現するということですね。
the_posts_pagination()
pagination するには the_posts_pagination() を使います。
これだけで基本OK。楽チンですね(^_^)
ということで、 parts/posts-pagination.php のコードは以下のようになります。
もはやテンプレート部品にする必要がないくらい短いコードとなりました(^_^;)
<?php the_posts_pagination(); ?>
投稿一覧を表示させてみる
これで、とりあえず投稿一覧を表示させることができるようになりました。
ただこのままだと、アイキャッチ画像の大きさがマチマチなのであまりうまくありません。
なので、画像の大きさだけ揃えるようなCSSを書いておきます。
幅は300px、ただし最大で親要素の40%とします。さらにアスペクト比を3:2としました。
アスペクト比を固定するやり方はこちらを参考にしました。
ということで、CSSは↓こんな感じとなりました。
.post-list .post-thumbnail {
float: left;
margin: 0 20px 0 0;
max-width: 40%;
position: relative;
width: 300px;
}
.post-list .post-thumbnail:before {
content: '';
display: block;
padding-top: 66.67%; /* aspect hack */
}
.post-list .post-thumbnail img {
height: 100%;
left: 0;
object-fit: contain;
position: absolute;
top: 0;
width: 100%;
}
WordPressのテーマでは style.css は必須ファイルとなっていますが、
何故か自動では読み込んでくれないので、こちらを参考に読み込ませます。
テーマの基準フォルダは get_template_directory_uri() で取得できるので、
これを元に対象ファイルのパスを設定するのが良さそうです。
ということで、functions.php に以下のようなコードを追加しました。
ハンドル名は重複しないようにそれっぽい名前にすれば良いかと思われます。
なお、依存関係がある場合は読み込ませる順番に注意です。
add_action( 'wp_enqueue_scripts', function() {
$base = get_template_directory_uri();
wp_enqueue_style( 'rf-style', $base . '/style.css' );
});
それでは現段階での動作を確認してみましょう。
XAMPP上に構築したローカルなWordPress環境で自作テーマを有効にしてみました。
アイキャッチ画像用のCSSしか入っていませんが、投稿一覧を表示することが出来ました。
これだけでもそれなりに投稿一覧として成立しそうですね。
そして結果は↓こんな感じ。全体をキャプチャしたので長いです(^_^;)
paginationがしっくりこない
見た目の方はCSSで好きなようにやればよいのでどうにでもできそうですが、
ちょっとしっくりこないのが pagination の結果。
どういうことかというと、
1ページ目 ➔ 「1 2 … 61 次へ」
2ページ目 ➔ 「前へ 1 2 3 … 61 次へ」
3ページ目 ➔ 「前へ 1 2 3 4 … 61 次へ」
4ページ目 ➔ 「前へ 1 … 3 4 5 … 61 次へ」
5ページ目 ➔ 「前へ 1 … 4 5 6 … 61 次へ」
最終ページ ➔ 「前へ 1 … 60 61」
上記のようになるわけですが、要素数が一定になりません。
「数字」や「…」が入る箱を「スロット」と呼ぶことにすると、最小4個、最大7個となります。
個人的にはスロット数を固定にして、極力位置が決まるようにしたいのです。
そして1ページ目の「前へ」と最終ページの「次へ」はCSSの visibility: hidden; を使えば、
領域を確保した状態で消去することができますので、位置を固定させられます。
要するに以下のような感じにしたいのです。
番号が2桁以上になると多少ズレてしまうことになりそうですが、ほぼ位置を固定させることができると思います。
1ページ目 ➔ 「 1 2 3 4 5 ー 61 >」
2ページ目 ➔ 「< 1 2 3 4 5 ー 61 >」
3ページ目 ➔ 「< 1 2 3 4 5 ー 61 >」
4ページ目 ➔ 「< 1 2 3 4 5 ー 61 >」
5ページ目 ➔ 「< 1 ー 4 5 6 ー 61 >」
最終ページ ➔ 「< 1 ー 57 58 59 60 61 」
the_posts_pagination() の引数でどうにかできると良かったのですが、無理のようです・・・(T_T)
ん~どうしたものか・・・。
何かヒントになるようなことはないかと、WordPress本体のソースを読んでみることにしました。
そしたら pagination の結果は wp-includes/general-template.php にある paginate_links() で最終的に出力していることがわかりました。
んで、その部分が↓こんな感じ。
function paginate_links( $args = '' ) {
︙
$r = apply_filters( 'paginate_links_output', $r, $args );
return $r;
}
そうなんです!
paginate_links_output フィルターを使えば結果を書き換えることができるのです!!
ということで、functions.php に以下のようにフィルターを書いてみました。
注意点としては、結果を全部書き換えてしまうので、優先度を低くして最後に呼ばれるようにすることです(^_^;)
少々強引ですが期待したような結果にすることができました。
add_filter( 'paginate_links_output', function( $links, $args ) {
// オリジナルのpaginationのやり方がしっくりこないので全部書き換える。
// 参照 → paginate_links() @ wp-includes/general-template.php
$links = '';
$total = $args['total'];
if ($total > 1) {
$current = $args['current'];
$slotMax = 7; // スロットの数は7以上の奇数とする。
$slots = [];
if ($slotMax < $total) {
$t = floor($slotMax/2);
$ofs = 0;
if ($current > $t + 1) {
$ofs = $current - ($t + 1);
if ($ofs > $total - $slotMax) {
$ofs = $total - $slotMax;
}
}
for ($i=1; $i<=$slotMax; $i++) {
$slots[] = $i + $ofs;
}
$slots[0] = 1;
$slots[$slotMax-1] = $total;
if ($slots[1] != 2) {
$slots[1] = -1; // '…';
}
if ($slots[$slotMax-2] != $total-1) {
$slots[$slotMax-2] = -1; // '…';
}
} else {
$slotMax = $total;
for ($i=1; $i<=$slotMax; $i++) {
$slots[] = $i;
}
}
if ($current > 1) {
$links .= '<a class="page-number prev" href="' . get_pagenum_link( $current - 1 ) . '">◀</a>';
} else {
$links .= '<span class="page-number hidden">◀</span>';
}
for ($i=0; $i<$slotMax; $i++) {
$t = $slots[$i];
if ($t < 0) {
$links .= '<span class="page-number dots">…</span>';
} else {
if ($current == $t) {
$links .= '<span aria-current="' . esc_attr( $args['aria_current'] ) . '" class="page-number current">' . $t . '</span>';
} else {
$links .= '<a class="page-number target" href="' . get_pagenum_link( $t ) . '">' . $t . '</a>';
}
}
}
if( $current < $total ) {
$links .= '<a class="page-number next" href="' . get_pagenum_link( $current + 1 ) . '">▶</a>';
}
else {
$links .= '<span class="page-number hidden">▶</span>';
}
}
return $links;
}, 999, 2 ); // 全部書き換えるので、優先度を低くして最後に呼ばれるようにする!
次回に続きます。