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

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

実際のコード

<!-- 評価あり -->
<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 = get_posts(array(
    'posts_per_page' => 10,
    'cat' => 3,  // 必要に応じてカテゴリーなどを指定
    'meta_key' => 'ratings_average',
    'orderby' => 'meta_value_num',  // 数値の大きい順に並び替え
    'order' => 'DESC'
));
foreach ( $ratingloop as $post ) :
?>
 
********** ループ内 **********
 
<?php endforeach; wp_reset_query(); ?>