ブログでは、記事下に投稿記事と同じカテゴリーの記事を並べる、ということをよくします。今回は、投稿した記事と同じカテゴリーの前後数件の記事を一覧出力します。要は、投稿した記事と同じカテゴリーでかつ、投稿した日付が近い日のものを一覧出力しよう、ということです。
動機
ブログにおいては、投稿した記事と同じカテゴリーの記事を記事下に一覧出力するのが一般的です。その時、同一カテゴリーの最新記事であるか、あるいはランダムに並べたものであることがたいていのようです。
それはそれでよいのですが、投稿した記事の前後の記事を一覧出力したい、というケースもあるものと思います。たとえば連載記事です。全20回の連載記事を一つのカテゴリでまとめて、記事下に最新記事を10件表示するようにした場合、たとえ第5回の記事のページでも、記事下に一覧出力されるのは第11回〜第20回となってしまいます。しかし、この場合読者に優しいのは、第5回の前後、すなわち第1回〜第4回および第6回〜第10回が一覧出力されることではないでしょうか。
このサイトは、連載記事は多くありませんが、ひとつながりのテーマについて、ある時期に集中して記述することが多いです。したがって、記事下に出力するのは、最新記事よりも、投稿記事の前後の記事であるほうが、より関連性が高くなる可能性が高いと考え、今回の実装に至りました。
完成形
前後合わせて10件の記事を出力します。基本は前5件、後5件ですが、記事数が5件に満たない場合は前2件後8件などとします。合計が10件に満たない場合は、すべて表示されます。また、投稿記事は一覧内に出力しません。カテゴリーが複数ある場合は、すべてのカテゴリーについて一覧出力します。その際、一度出力した記事は他カテゴリー内で出力しません。
2016年11月現在、この記事の下の出力がまさにそうです。一応画像を貼ります(日付出力部分はソースコードに含んでいません。念のため)。
だいたい上のような感じを目指します。
ソースコード
ソースコードを以下に記述します。使用されている関数の意味や、どのファイルに適用すべきかなどは、より簡単な実装である「WordPress で同一カテゴリの記事タイトルを記事下に表示(複数カテゴリ)」の記事を参照してください。この記事に書いてあることがわかれば大丈夫です。逆にわからないと厳しいと思います。
<?php
// 投稿記事のカテゴリーを取得する
$post_cat_ary = get_the_category();
$post_cat_id = array();
foreach( $post_cat_ary as $post_cat ):
$post_cat_id[] = $post_cat->cat_ID;
endforeach;
$args = array( 'include' => $post_cat_id );
$categories = get_categories( $args );
// 投稿記事のIDと、除外するIDリストの配列
$post_id = get_the_ID();
$post_id_array = array();
// カテゴリー毎にループ処理
foreach( $categories as $category ):
// 投稿記事のカテゴリ内で新着から何番目かを確認
$args = array( 'posts_per_page' => 999, 'category' => $category->cat_ID, 'exclude' => $post_id_array );
$posts = get_posts( $args );
$posts_ids = array();
foreach ( $posts as $post ) {
$posts_ids[] += $post->ID;
}
$post_pos = array_search( $post_id, $posts_ids );
// post_id_array に投稿記事のIDを追加
$exclude_ids = array();
$exclude_ids[] = $post_id_array;
$exclude_ids[] += $post_id;
// 投稿記事がカテゴリー内で新着5件内だった時の処理
$post_offset = $post_pos - 5;
if ( $post_offset < 0 ) {
$post_offset = 0;
}
// 投稿記事の順番 - 5件 をオフセットして記事一覧を取得
$args = array( 'posts_per_page' => 10, 'offset' => $post_offset, 'category' => $category->cat_ID, 'exclude' => $exclude_ids );
$posts = get_posts( $args );
if ( sizeof($posts) > 0 ):
echo '<h2><a href="'.get_category_link( $category->term_id ).'">'.$category->cat_name.'</a> の記事</h2>';
echo '<ul>';
$count = 0;
foreach( $posts as $post ):
// 投稿記事がカテゴリー内で最新だった時
if ( $post_pos == 0 ) {
if ( $count == 0 ) {
echo '<li>---本記事(カテゴリー内最新)---</li>';
}
}
// 記事の表示
echo '<li><a href="'.get_permalink().'">'.get_the_title().'</a></li>';
// 一度出た記事を二度表示しない
$post_id_array[] = get_the_ID();
if ( ($post > 0) && ($post_pos < 5) ) {
if ( $count == $post_pos -1 ) {
echo '<li>---本記事---</li>';
}
} else {
if ( $count == 4 ) {
echo '<li>---本記事---</li>';
}
}
$count += 1;
endforeach;
echo '</ul>';
endif;
endforeach;
$post = get_post($post_id);
?>
大まかには以下のことをしています。
- 投稿記事のカテゴリーを取得する($categories)
- 取得した各カテゴリーについて、次のループ処理を行う
- 投稿記事が、そのカテゴリーで新着から何番目かを確認する($post_pos)
- $post_posから前後5件表示したいので、$post_pos-5 をオフセットしてget_posts()
- get_posts()の結果を$postにして出力する
- 3-5を投稿記事のカテゴリーの数だけ出力
- $postを元に戻す
最後はメタデータに影響するのでなにげに重要です。$postをいじるのは行儀が悪いのかしら……。そろそろWordPressちゃんと勉強しようか……。
一度出た記事を表示しないなどの処理もしているので、コードがちょっと複雑になっています。詳細については、コメントでわかるように書いているつもり…です。
コメント