と言ってもカテゴリーページの表示を少し変えただけ…。

WordPress の記事にレーティング機能を追加できるプラグインとして有名な「WP-PostRatings」。ajaxで画面の遷移なくレーティングが反映されたり、設置が簡単な事からありがたく使わせていただいているのですが、一つだけ不満な点があります。

このプラグインでは、画像(img要素)を直接書き出してレーティングを表示する方法となっているので、下記のようなコードが吐き出されます。

// スター画像一つに付き
<img src="http://example.com/wp-content/plugins/wp-postratings/images/stars_crystal/rating_on.gif" alt="10 投票, 平均値/最大値: 3.50 / 5" title="10 投票, 平均値/最大値: 3.50 / 5" class="post-ratings-image" />

///// スターの数(5個分)繰り返し /////

<em>3.50</em>/5 (10人の評価)

これは、5段階評価の設定で、<?php echo the_ratings_results(get_the_id()); ?> としてカテゴリーページでは投票できないようにしているものですが、いずれにしても一つの記事に対してこのコードが付いてきます・・・。

ご想像の通りで、1ページあたり20の記事を表示している場合、1ページに占める余分な?コードが多くなってしまい(100個の画像コード…)、画像に付けられている alt 属性のことも考えると、あまり嬉しくない状況なのです。

解決策としてまず思いついたのが3つ

  1. GD Star Rating など、他のプラグインを利用する
    ┗高機能すぎて挫折…
  2. プラグインをカスタマイズ
    ┗その知識を持ち合わせていないので無理…
  3. alt 属性などの一部分だけ削除・書き換え
    ┗アップデートの時が面倒…

以下、カテゴリーページでも評価してもらうコードを使っている場合には利用できません。また、シングルページでは利用できません。(評価できなくなります)

そこで、WP-PostRatingsが利用しているカスタムフィールドを利用して、プラグイン本体のカスタマイズなしで、コードをすっきりさせようと思います。

WP-PostRatings は、ratings_average という meta_key にレーティングの値を、ratings_users という meta_key にレーティングした人数を格納していきます。なので、それぞれの値を取り出して、必要な加工を施せば実現できるはずです。

<div class="rating"><?php
$ave = get_post_meta( $post->ID, 'ratings_average', true );
if ( !empty($ave) ) {
	$user = get_post_meta( $post->ID, 'ratings_users', true );
	$per = $ave * 16;
	echo '<span style="width:' . $per . 'px;">Rating: </span>';
	echo '<em>' . $ave . '</em>/5 (' . $user . '人の評価)';
} else {
	echo '(未評価)';
}
?></div>
  • 1行目: 全体を括るタグ。サンプルは div にしてありますが、p、dd、li などでも。
  • 2行目: レーティングの値を取り出し、$ave という変数に落とす。
  • 3行目: もし ratings_average の値があれば。(評価されていれば)
  • 4行目: さらに評価した人数を取り出し変数に落とす。
  • 5行目: レーティングの値を画像の長さに変換する。星一つの長さが16pxなので、評価値×16として、$perという変数に落とす。
  • 6行目: span に長さのスタイルを与える。評価値2.5なら「2.5×16=40px」で、全体の半分の長さになる。
  • 7行目: 必要に応じて評価値やレーティングした人数を書き出す。
  • 8、9行目: 評価されていない記事の場合は「未評価」と書き出す。

「変数に落とす」という表現、使い方合ってるのかなぁ・・・?

実際のコード

<!-- 評価あり -->
<div class="rating"><span style="width:56px;">Rating: </span><em>3.5</em>/5 (10人の評価)</div>

<!-- 未評価の場合 -->
<div class="rating">(未評価)</div>

用意する画像

プラグインで用意されている、on、off のスターを一枚の画像にしたものです。長さが80px、高さが32pxになります。(ここでは rating.png とします。)

スタイル

.rating {
	height:16px; line-height:16px;
	position:relative;
	background:url("/img/rating.png") no-repeat left bottom;
	text-indent:90px;
}
.rating span {
	text-indent:-9999px;
	position:absolute; left:0; top:0;
	background:url("/img/rating.png") no-repeat left top;
}

背景画像の指定がうまくいくように、div class="rating" の高さを16pxに指定し、text-indent:90px(画像の長さ80px+マージン10px)で画像とテキストが重ならないように調整。また、span に text-indent:-9999px をつけて「Rating: 」というテキストを飛ばしています。

IE 6,7,8 / Opera 5 / Firefox / Chrom で問題なく表示されますが、もっとスマートな方法があるかもしれません。

サイドバーなどで利用

WP-PostRatings では、レーティング順や評価人数が多い順など、記事を表示するテンプレートが用意されていますが、この meta_key を利用すれば、サムネイルを加えたり、好みの表示にすることもできます。

カテゴリーID3 の記事を、レーティングの高い順に10件表示

<?php
$ratingloop = new WP_Query( array(
	'cat' => 3, // 必要に応じてカテゴリーなどを指定
	'meta_key' => ratings_average,
	'orderby' => meta_value_num, // 数値の大きい順に並び替え(WP3.0~)
	'order' => DESC,
	'posts_per_page' => 10
) );
while ( $ratingloop->have_posts() ) : $ratingloop->the_post();
?>

********** ループ内 **********

<?php endwhile; wp_reset_query(); >