カテゴリー
XOOPS

XOOPSモジュール版WordPressでAjaxを使った投票システムを作ってみた

[2007.4.11 追記]
グラフ付きも作ってみました。グラフ付き投票システムはこちら
[2007.4.11 追記おわり]

ちょっと前にXOOPSモジュール版WordPressで記事の閲覧回数をカウントして表示する仕組みをつくりました
これは、おすすめの記事を訪問してくれた人の目にとまるところに表示することで便利に使ってもらおうという意図があったのですが、どうもランキングを見ていると、たいして役に立たなさそうなリア・ディゾンの記事が一位になっていて、意味をなしていないような気がしてきたので別の仕組みを導入することにしました。

そこで考えたのが、実際に記事を見た人に投票してもらう仕組み。閲覧数が多いというのは、実際はGoogleでたまたま上位に表示されているだけで、必ずしもその記事が有用であるとは言えないわけです。じゃあどうやって、有用かどうかを評価するかと考えると、やっぱり実際に記事を読んだ人に評価してもらうしかないかな、と。

少しでも投票することに対する負担を軽減するためにAjax(Asynchronous Javascript?+ XMLの略。JavascriptとXMLを使った非同期通信のこと)を使って画面遷移なしで投票できるようにしてみました。よくある投票の仕組みって画面遷移するから自分も押さない事が多かったんですよね。Ajaxならバックグラウンドで処理してくれるから少しはマシかと。

まずは投票結果を保存するテーブルを作成。
以下のスクリプトをMySqlのコマンドやphpMyAdminなどで実行してください。

CREATE TABLE `xoops_wp_popularity` (
? `postnumber` int(11) NOT NULL default '0',
? `good` int(11) NOT NULL default '0',
? `bad` int(11) NOT NULL default '0',
? PRIMARY KEY? (`postnumber`)
) TYPE=MyISAM;

サーバー側がvote.php。Webサーバーのルートディレクトリに「Ajax」というディレクトリを作成して置きます。
最初に記事IDが数値かどうかを判断しているのでSQLインジェクションは防げていると思うけど、どうだろう。かなり適当感漂うけど、そのうちリファクタリングします。 行が長いので途中で改行しています。

$conn = mysql_connect("server","user","password");

上記のserver,user,passwordには環境に合わせてデータベース接続に必要な情報を入れてください。

[追記]
JavaScriptから受け取ったIDをそのまま表示している部分があったのでコメントアウトしました。受け取った値が数値かどうかを検証しているので問題はないはずですが、後で仕様変更で文字もOKになったときに、タグを埋め込まれたりしてセキュリティーホールになってしまうかもしれないですから。

<?php
//美乳
//WordPress人気投票(vote.php)
$fail = "fail";
$id = $_GET['id'];
if (!is_numeric($id)){
?print $fail;
?return;
}
$conn = mysql_connect("server","user","password");
mysql_select_db("xoops");
switch ($_GET["vote"]){
?case "good" :
??voteGood($id);
??//print "good: " . $id;
??break;
?case "bad" :
??voteBad($id);
??//print "bad: " . $id;
??break;
?default :
??print($fail);
}
function voteGood($p_number){
?$result = isExsits($p_number);
?$test = 0;
?while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
??$row[1] += 1;
??$sql = sprintf("update xoops_wp_popularity
set good = %d where postnumber = %d;", $row[1], $row[0]);
??@mysql_query($sql);
??$test = 1;
?}
?if ($test == 0) {
??$sql = sprintf("insert into xoops_wp_popularity(postnumber, good, bad)
values(%d, 1, 0);",$p_number);
??@mysql_query($sql);
?}
}
function voteBad($p_number){
?$result = isExsits($p_number);
?$test = 0;
?while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
??$row[2] += 1;
??$sql = sprintf("update xoops_wp_popularity set bad = %d
where postnumber = %d;",$row[2],$row[0]);
??@mysql_query($sql);
??$test = 1;
?}
?if ($test == 0) {
??$sql = sprintf("insert into xoops_wp_popularity(postnumber, good, bad)
values(%d, '0', '1');",$p_number);
??@mysql_query($sql);
?}
}
function isExsits($p_number){
?$sql = sprintf("select postnumber, good, bad from xoops_wp_popularity
where postnumber = %d;",$p_number);
?return mysql_query($sql);
}
?>

以下は、Ajaxで使うJavascript。ファイル名はvotescript.jsとしてvote.phpと同じルートのajaxディレクトリに入れます。
vote.phpを呼び出しています。
あと、prototype.js(バージョンは1.5.0)を使っています。 prototype.jsもajaxディレクトリにいれます。

// JavaScript Document
// 美乳(votescript.js)
function voteGood(id)
{
?displayProgress();
?new Ajax.Request("/ajax/vote.php?id=" + id + "&vote=good",
{ method: 'get', onSuccess: displayResult, onFailure : displayFail });
}
function voteBad(id)
{
?displayProgress();
?new Ajax.Request("/ajax/vote.php?id=" + id + "&vote=bad",
{ method: 'get', onSuccess : displayResult ,onFailure : displayFail});
}
function displayProgress()
{
?$("vote-result").innerHTML = '投票処理中・・・'
}
function displayResult(responseHttpObj)
{
?if (responseHttpObj.responseText == 'fail')
?{
??$("vote-result").innerHTML
= 'ごめんなさい、サーバーに問題が発生していてうまく投票できませんでした';
?}else{
??$("vote-result").innerHTML = '投票ありがとうございます!';
?}
}
function displayFail()
{
?$("vote-result").innerHTML = 'サーバーエラー!';
}

XOOPSのテンプレートにJavaScriptの読み込みを追加します。
XOOPSのディレクトリのthemeディレクトリの中を探っていくとtheme.htmlがあるはずです。
これのheadタグの間に

<script language="javascript" src="/ajax/prototype.js"></script>
<script language="javascript" src="/ajax/votescript.js"></script>

を追加します。

WordPressのcomments-template.phpに以下のような行を追加します。
一行目の

<?php /* Don't remove this line */ if (!defined('XOOPS_ROOT_PATH')) { exit; }?>

となっている所の下に追加するといいでしょう。

comments-template.phpはxoopsの中の「modules/wordpress/themes/(テーマ名)」の中にあります。

<div class="vote-box" id="vote-result">
この記事は良かったですか?
<input type="submit" name="Submit" value="良い"
onClick="voteGood(<?php print($post->ID); ?>);">
<input type="submit" name="Submit" value="イマイチ"
onClick="voteBad(<?php print($post->ID); ?>);">
</div>

これでAjaxな投票ボタンは表示されます。

ランキングの表示は以下のような感じのソースをカスタムブロックに入れると良いでしょう。

global $xoopsUser,$xoopsDB;
$sql = "select m.postnumber, m.good ,p.post_title
FROM ".$xoopsDB->prefix('wp_popularity')." m
INNER JOIN ".$xoopsDB->prefix('wp_posts')." p
ON m.postnumber = p.ID WHERE m.good <> 0 ORDER BY m.good DESC LIMIT 10";
$res = $xoopsDB->query($sql);
$rank=0;
while($value = $xoopsDB->fetchArray($res)){
?$rank = $rank + 1;
?echo $rank.".<a href=https://a-tak.com/xoops/modules/wordpress/index.php?p=
.$value["postnumber"]."&more=1&c=1">".$value["post_title"]
."(".$value["good"]." votes)</a><br/>";
}
echo "11位以降は
<a href="https://a-tak.com/xoops/modules/info/index.php?id=11">こちら</a><br/>";
echo date("m月d日 H時i分")." 更新";

こんな感じでAjaxな投票ボタンが出来た。
でも、よく考えるとXMLなんて全然使ってないのでAjax(エージャックス)じゃなくてAjaだな。
Aja・・・アジャ?なんかかっこわるい。

PHPとかよくわからずに作っているのでソースがやたら汚かったり、もしかしたらセキュリティーホールがあるかも。何か問題あったら教えて下さい。

この記事を書いた人: A-tak

A-tak.com(えいたっく どっとこむ)の管理人。
Apple野郎なおっさんでしたが、ちょっと最近のAppleには飽き気味。
A-tak.comは2002年2月から運営(前身のサイトは1999年3月から)。今年で18年目!

Twitter
Mastodon
Facebook

コメントは受け付けていません。