以前 WordPress テーマを Stinger に切り替えてから、あまり詳細を気に留めることなくそのまま使っていたのですが、近頃になって投稿ページの記事下に出る関連記事の表示内容に、あまり関連してないようなエントリがよく表示されることが気になっていました。
その原因調査と、その対応にちょっとしたカスタマイズを入れた子ネタのメモです。
※以下、Stinger バージョン20140327 でのソースを前提にした説明となります。
原因
single.php の関連記事の表示部分を見てみます。
[php firstline=”60″]
<!–関連記事–>
<h4 class="kanren">関連記事</h4>
<div class="sumbox02">
<div id="topnews">
<div>
<?php
$categories = get_the_category($post->ID);
$category_ID = array();
foreach($categories as $category):
array_push( $category_ID, $category -> cat_ID);
endforeach ;
$args = array(
‘post__not_in’ => array($post -> ID),
‘posts_per_page’=> 10,
‘category__in’ => $category_ID,
‘orderby’ => ‘rand’,
);
$st_query = new WP_Query($args); ?>
<?php
if( $st_query -> have_posts() ): ?>
<?php
while ($st_query -> have_posts()) : $st_query -> the_post(); ?>
<dl>
<dt> <a href="<?php the_permalink() ?>" title="<?php the_title_attribute(); ?>">
<?php if ( has_post_thumbnail() ): // サムネイルを持っているときの処理 ?>
<?php echo get_the_post_thumbnail($post->ID, ‘thumb110’); ?>
<?php else: // サムネイルを持っていないときの処理 ?>
<img src="<?php echo get_template_directory_uri(); ?>/images/no-img.png" alt="no image" title="no image" width="110px" />
<?php endif; ?>
</a> </dt>
<dd>
<h4 class="saisin"> <a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a></h4>
<p class="basui">
<?php echo mb_substr( strip_tags( stinger_noshotcode( $post->post_content ) ), 0, 50 ) . ”; ?></p>
<p class="motto"><a href="<?php the_permalink(); ?>">記事を読む</a></p>
</dd>
</dl>
<?php endwhile;
?>
<?php else:
?>
<p>記事はありませんでした</p>
<?php
endif;
wp_reset_postdata();
?>
</div>
</div>
</div>
</div>
<!–/kizi–>
<!–/関連記事–>
[/php]
関連記事の表示には、ざっくり次のようなことがされているようです。
- 表示している投稿のカテゴリーを全部取得
- 取得したカテゴリーに属している投稿をランダムで10件取得
- 取得した投稿を関連記事に表示
この処理を見て、このブログのカテゴリーの管理方法に原因があることに気付きました。
例えば、当ブログでは現在上記のような親子階層を持つカテゴリー構造を作っているんですが、「生活」+「子育て」に属する投稿と、「生活」+「将棋」に属する投稿はどちらも「生活」に該当するので、関連記事として表示されるわけです。動きとしては全然問題無いんですが、「子育て」と「将棋」の記事が関連して出てきてはそりゃあまり具合がよろしくありませんよね・・・。
カスタマイズ
根本的な原因はカテゴリー設計が良くないことだなーと反省はしましたが、そちらを直すのは色々面倒なので、とりあえず暫定的な対応で関連記事をカスタマイズしてみました。
カスタマイズ方針としては、「表示している投稿の全カテゴリーから親階層のカテゴリーは対象外にする」という感じです。
[php firstline=”60″ highlight=”71,72,73″]
<!–関連記事–>
<h4 class="kanren">関連記事</h4>
<div class="sumbox02">
<div id="topnews">
<div>
<?php
$categories = get_the_category($post->ID);
$category_ID = array();
foreach($categories as $category):
array_push( $category_ID, $category -> cat_ID);
endforeach ;
// 取得したカテゴリーをIDでソートして、先頭のレコード(親カテゴリー)は除く
sort( $category_ID);
$arr = array_shift($category_ID);
$args = array(
‘post__not_in’ => array($post -> ID),
‘posts_per_page’=> 10,
‘category__in’ => $category_ID,
‘orderby’ => ‘rand’,
);
$st_query = new WP_Query($args); ?>
<?php
if( $st_query -> have_posts() ): ?>
<?php
while ($st_query -> have_posts()) : $st_query -> the_post(); ?>
<dl>
<dt> <a href="<?php the_permalink() ?>" title="<?php the_title_attribute(); ?>">
<?php if ( has_post_thumbnail() ): // サムネイルを持っているときの処理 ?>
<?php echo get_the_post_thumbnail($post->ID, ‘thumb110’); ?>
<?php else: // サムネイルを持っていないときの処理 ?>
<img src="<?php echo get_template_directory_uri(); ?>/images/no-img.png" alt="no image" title="no image" width="110px" />
<?php endif; ?>
</a> </dt>
<dd>
<h4 class="saisin"> <a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a></h4>
<p class="basui">
<?php echo mb_substr( strip_tags( stinger_noshotcode( $post->post_content ) ), 0, 50 ) . ”; ?></p>
<p class="motto"><a href="<?php the_permalink(); ?>">記事を読む</a></p>
</dd>
</dl>
<?php endwhile;
?>
<?php else:
?>
<p>記事はありませんでした</p>
<?php
endif;
wp_reset_postdata();
?>
</div>
</div>
</div>
</div>
<!–/kizi–>
<!–/関連記事–>
[/php]
これで、子階層のカテゴリーを持つ記事だけ関連表示されるようになったので、前よりいい感じになりました。
ちなみに、上記のカスタマイズはあくまでうちのブログ用に下記条件が前提となっています。
- 必ず各投稿が親子それぞれのカテゴリーに属している
- 親カテゴリーのID < 子カテゴリーのID になっている(必ず親→子の順に登録している想定なので)
ちゃんとやるなら、最上位階層にあるカテゴリーかどうか判定して除く、とかやるのが正しいやり方かと。どのブログでも流用できるカスタマイズではないことにご注意ください・・・。