【WordPress】シングルページでカスタムフィールドを利用した関連記事一覧の手動表示とページングの設置

こんにちは。最近、年下の女の子にどう接したらいいかわからない土橋です。
もう自分がおじさんになったのか、それとも元々女の子との会話が苦手なのかわかりませんが、すぐに周りに助けを求めてしまいます。

そんなことより本題です。今回は、Wordpressのシングルページに関連記事をカスタムフィールドを使って手動で表示し、そこにページングを付けるというものです。
カテゴリーなどに合わせて関連記事を表示させる方法がありますが、今回の方法では手動で記事を選べるので、ピンポイントで関連記事を表示させることができます。
シングルページでページングというものなかなかの曲者で、少し手間がかかりますが実現可能なのでここに残します。

カスタムフィールドで関連記事を手動で表示

まずは最初に関連記事の設定ですが、ここはプラグインに任せてしまいます。「Advanced Custom Fields」というプラグインが有名かつ便利なので、こちらを利用します。関連記事の設定は、下の画像のようにフィールドタイプに「関連」に選ぶだけです。今回はフィールド名を「relation_post」とします。

カスタムフィールドの設定

「Advanced Custom Fields」の詳しい使い方は、下記のブログも参考にしてください。
http://kotori-blog.com/wordpress/advanced-custom-fields/

それでは、関連記事の設定ができたという前提で、シングルページのカスタマイズに移ります。

シングルページに関連記事の一覧を表示

single.php、またはカスタム投稿のシングルページに以下を入力していきます。
ソースにコメントを記載しているのでわかりやすいと思うのですが、メインループの他にサブループで関連記事の一覧を表示します。

クエリのパラメーターに「post__in」というものがあるので、これにカスタムフィールドで登録した関連記事のIDを割り当てます。

あとはループさせるだけですね。ループ内は特に変わるものはありません。
最後にページングを設置しています。


<?php // 配列の初期化
$array = array();
// カスタムフィールドの関連記事を配列objectへ
$object = get_field('relation_post');
// 配列arrayに関連記事のIDを格納
foreach($object as $value){ $array[] = $value->ID;}

	$paged = (get_query_var('paged')) ? get_query_var('paged'): 1;

	// post__inに関連記事IDの配列を指定
	$relation_archive = array(
	    'post_type' => array('post'),
	    'paged' => $paged,
	    'post__in' => $array
	);

	// クエリを実行する
	$wp_query = new WP_Query($relation_archive);
?>

<?php // 関連記事の投稿がある場合のみ表示
 if($wp_query -> have_posts()):
?>
<?php // 関連記事のループ
while ($wp_query->have_posts()) : $wp_query->the_post();
?>
<article>
	<a href="<?php the_permalink(); ?>">
	<?php if ( has_post_thumbnail() ) : ?>
	<?php the_post_thumbnail('thumbnail'); ?>
	<?php endif; ?>
	</a>
<h1><?php the_title(); ?></h1>
<?php the_excerpt(); ?>
</article>
<?php
// ループの終了
endwhile;
// クエリのリセット
wp_reset_postdata(); ?>

<div class="paging">
<?php // ページングの出力
global $wp_rewrite; $paginate_base = get_pagenum_link(1);
if(strpos($paginate_base, '?') || ! $wp_rewrite->using_permalinks()){
	$paginate_format = '';
	$paginate_base = add_query_arg('paged','%#%');
	}
	else{
	$paginate_format = (substr($paginate_base,-1,1) == '/' ? '' : '/') .
	user_trailingslashit('page/%#%/','paged');;
	$paginate_base .= '%_%';
	}
	echo paginate_links(array(
	'base' => $paginate_base,
	'format' => $paginate_format,
	// 変数をクエリ実行の$wp_queryと同じにする
	'total' => $wp_query->max_num_pages,
	'mid_size' => 4,
	'current' => ($paged ? $paged : 1),
	'prev_text' => '前の'.get_option('posts_per_page').'件',
	'next_text' => '次の'.get_option('posts_per_page').'件',
	));
?>
</div>
<?php else: ?>

関連記事はありません。

<?php endif; ?>

ページングが動かない・・・?

ここまでやってできたーと思っていたら落とし穴が。なんとページングが動きません。
URLにhttp://domain.com/post_name/2/のように打ち込んでも、http://domain.com/post_name/にリダイレクトされます。

これを解決するために、function.phpに以下を追加します。関連記事を表示したいページが投稿なのか、カスタム投稿なのかで必要な処理が変わります。

投稿ページのリダイレクト禁止

<?php
function my_disable_redirect_canonical( $redirect_url ) {
	if ( is_single() ) $redirect_url = false;
	return $redirect_url;
}
add_filter('redirect_canonical','my_disable_redirect_canonical');
?>

カスタム投稿のシングルページのリダイレクト禁止

<?php
function
my_disable_redirect_canonical( $redirect_url ) {
 if ( is_singular( 'custom_post_name' ) )
 // カスタム投稿名を指定
 	$redirect_url = false; return $redirect_url;
}
add_filter('redirect_canonical','my_disable_redirect_canonical');
?>

まとめ

リダイレクトの部分はもう少し適切な方法があるかもしれませんが、これで目標の表示を実現することができました。これからも「かゆいところに手が届く」カスタマイズを目指して勉強していこうと思います。

それでは、また今度。