関連する投稿を単一記事内に表示する
今回は「単一記事と同じカテゴリ」に属する記事を4つ表示するブロックを作る方法を書きます。
別に3つでも10個(そんなにいらんがな…)でも方法は同じです。
このブログでの関連記事表示は、当初プラグインで実装しようと思っていたのですが…。
- 出力されるHTMLタグに無駄な物が多すぎて、しかもその出力内容を管理画面やテーマで調整できない(するとしたらプラグインのソースコードをいじるしかない)
- 関連記事を選ぶ基準が「同一カテゴリ」「同一タグ」。実は意外と単純だった(WP_Queryを使います→後述)
…以上の理由から、むしろ同等の機能をテーマで作ったほうが早いと気づいたのでした。
さて、記事一覧を出力する関数として「the_post()」があります。
通常、条件分岐(このケースではhave_posts()を併用する)やループ処理と一緒に使用しますが、条件に当てはまるすべての記事一覧を出力します。
一方、WP_Queryクラスで呼び出すthe_post()は、現在の記事に関する情報を取り出します(これもループ内で使用します)。
また、何らかの方法で既に現在の記事の情報を取得している場合、記事タイトル・投稿ID・カテゴリ等を格納している「$post」という変数があります。
これは「global $post;」という感じで、グローバル変数として呼び出して使います。
以上の関数や変数を利用すれば、タイトル、投稿ID、投稿者名、投稿日時、カテゴリなどで条件を指定して、それらに当てはまる記事を決められた数だけ呼び出すことができます。
そして、それらを記事一覧などとして出力すればいいのです。
今回は表示中の単一記事と「同じカテゴリ」の記事を「4つ」出力して、「関連記事一覧」として、記事本文の下に表示するのが目的です。
WP_Queryで、WordPressで使っているデータベースから指定した条件に合った記事情報を取り出すため、条件を指定します。
<?php // 現在記事の情報が入っている$postをグローバル変数として宣言 global $post; // 現在記事のIDを変数に格納 $current_post = $post->ID; // 現在記事のカテゴリIDを変数に格納 $category_info = get_the_category(); foreach ($category_info as $category) { $current_category = (int) $category->term_id; } // WP_Queryのクエリーで使う条件を配列に格納し、直後の$the_query(インスタンス)で使用する $args = array( // ページあたりの記事数 'posts_per_page'=>4, // 対象の投稿タイプ 'post_type'=>'post', // 対象のカテゴリ(先に宣言した変数を使用) 'cat'=>$current_category, // 現在の記事を除外 'post__not_in'=>array($current_post), // 新しく修正された順に取得 'orderby'=>'modified', ); // ここで関連記事で表示したい記事の情報を取得 $the_query = new WP_Query($args); ?>
これで、条件にあった記事「現在記事と同一カテゴリの記事を新しい順に4つ」取り出せるようになりました。
次に取得した内容を使って、関連記事一覧を出力します。
以下のようなコードをsingle.phpなど単一記事出力用ファイルに書き込みます。
あるいは、関連記事一覧の部分だけ部分テンプレートファイルにして呼び出してもいいです。
この場合、出力したい場所に<?php get_template_part(‘related-posts’); ?>を書き呼び出します。
※()内にファイル名(拡張子を除く)を入れる。
// クエリーを実行した結果1記事以上見つかった場合 <?php if ($the_query->have_posts()) : ?> <ul class="entry-related-posts-list"> // 該当記事のタイトルを出力するためのループ処理 <?php while ($the_query->have_post()) : $the_query->the_post(); ?> <li class="entry-related-posts-item"> // 記事タイトルと記事へのリンクを出力 <a class="entry-related-posts-link" href="<?php the_permalink(); ?>"><?php the_title(); ?></a> </li> <?php endwhile; ?> // ループ処理終わり // ループ処理終了後、他にも記事クエリ($post等)を使う場合、ここでクエリの内容と記事のデータをリセットする <?php wp_reset_postdata(); wp_reset_query(); ?> </ul> // 1記事も見つからなかった場合 <?php else: ?> // テーマ内のlanguage関連ファイル(拡張子po)より、該当項目のメッセージを出力(_eはecho相当のコマンドとセットの翻訳出力方法) <p class="info"><?php _e('Sorry, no posts matched your criteria.', 'customtheme'); ?></p> <?php endif; ?> // 条件分岐終わり
レイアウト等は別途CSSで指定します。
ループ処理直後の「wp_reset_postdata()」や「wp_reset_query()」は、関連記事表示関連処理より後にWP_Query()や$postを使う場合は必須となります。
…というのも、それらを使い忘れてクエリ内容や取得した$postの内容をリセットしておかないと、処理結果が奇妙なことになるときがあるからです。
※今回はわかりやすくするため、自作テーマで使ったものより簡略化したものを前述のコードとして掲載しています。