2012-02-21

[jQuery/PHP] 投票などページ遷移せずにカウントアップした情報をファイルに書き込み

タイトルのとおりなのですが、投票システムのようなもので、
クリックしたらページ遷移することなく、その場ですぐにカウントアップされ、
なおかつ、サーバーのファイルにカウントアップした数を書き込む、という処理です。
やや適当な部分もありますが、だいたいこんな感じで動きます。

※2012-11-09修正
お問い合わせをいただき、あらためてソースを見返したところ、
あまりに適当だったので、全面的に修正し、デモページもアップしました。
中途半端なソースを出してしまいまして、申し訳ありませんでした。

デモページはこちら


getElementsByClassName.jsを使用しています。
ダウンロードはこちらから

Javascript
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script type="text/javascript" src="js/html5jp/dom/getElementsByClassName.js"></script>
<script type="text/javascript">
// --------------------------------------------------------
// 投票処理
// id : 書き込むファイル名(投票につき1つ設定)
// cls : 投票数を表示するクラス名
// --------------------------------------------------------
function Vote(id,cls) {
// 現在表示されている投票数から1カウントアップ
new_count = Number(document.getElementsByClassName(cls)[0].innerHTML) + 1;
// Ajaxでvote.phpを呼び出す<引数にid(ファイル名)とnew_count(カウントアップされた投票数)をセット>
$.ajax({
type: 'post',
url: 'vote.php',
data: {
'file_id': id,
'count': new_count
},
success: function(data){
// OKが戻ってきたらHTMLにカウントアップした値をセット
if(data == "OK") {
document.getElementsByClassName(cls)[0].innerHTML = new_count;
// OK以外はクッキーの時間指定の範囲内(のはず)
} else {
alert("10秒以内は連続投票できません!");
}
}
});
}
</script>


表示するメインのPHP
<div class="box boxcolor1">
<a href="javascript:void(0);" onclick="Vote('voteId1', 'cntClass1')" class="vote" title="">1に投票する!</a>
投票数:<div class="cntClass1"><?php echo getVoteCount('voteId1'); ?></div>
</div>

<?php
//----------------------------------------------------------
// 投票数取得関数
//----------------------------------------------------------
function getVoteCount($id) {
//ファイル名
$filename = "file/".$id.".cnt";
$fp = @fopen($filename, "r");
if ($fp) {
$vote = fgets($fp, 9182);
} else {
$vote = 0;
}
return $vote;
}
?>

※投票のファイルを格納するフォルダ「file」を作成して、属性を書き込み可能にしてください。

投票処理を行うPHP (vote.php)
<?php
$file_id = $_POST['file_id']; //ファイル名
$count = $_POST['count']; //投票数
$cookie_name = "vote_".$file_id; //クッキー名(ファイル毎)

// ------------------------------------------------
// クッキーが有効であれば何もしない
// ------------------------------------------------
if( isset($_COOKIE[$cookie_name]) ) {
// "NG"という文字列をJavascript側に返す
echo "NG";

// ------------------------------------------------
// クッキーがなければカウントアップ
// ------------------------------------------------
} else {
$count = $_POST['count'];

//カウントアップ
$filename = "file/".$file_id.".cnt";
$fp = @fopen($filename, "w");
flock($fp, LOCK_EX);
fputs($fp, $count);
flock($fp, LOCK_UN);
fclose($fp);

setcookie($cookie_name, $count, time()+10); // 10秒有効のクッキーを設定

// "OK"という文字列をJavascript側に返す
echo "OK";
}
?>

コメント / トラックバック 38 件

  1. 松田良平 より:

    失礼します。
    現在、HPに投票ページの設置を考えており
    検索していましたところ御社ページ
    http://aroun-d.com/2012/02/21/3724/
    にたどり着きました。

    初心者の為、うまく作動させることができません。
    こちらのソースを使用したサンプルページのようなものが
    ございましたら教えていただきたいのですが。

    お手数おかけいたしますが
    よろしくお願いいたします。

  2. nishi より:

    松田良平さま

    お問い合わせいただきまして、ありがとうございます。
    ほぼ自分のメモ程度のソースをアップしていましたので、
    うまく動作しなかったようで、ご迷惑をおかけしまして申し訳ありませんでした。

    デモページを作成して、ソースもかなり修正しましたので、
    よろしければ参考にしてください。

    別途メールでも送らせていただきます。
    よろしくお願いいたします。

  3. sakamoto より:

    ソースを使っても数値がNaNになりますが

  4. nishi より:

    sakamotoさま

    コメントありがとうございます。
    ブラウザ環境など教えていただけましたら調べてみますので、
    よろしければ再度ご連絡ください。
    メールにて連絡いただいても大丈夫です。

    よろしくお願いいたします。

  5. sakamoto より:

    再確認したところ、私の方に記述ミスがあり、修正後に正常動作を確認できました。
    お手数お掛けしますが私のコメントは邪魔になりますので削除をお願いします。
    ご迷惑をお掛けしました。
    改めて有益な情報に感謝致します。

  6. 三浦和紀 より:

    はじめまして。ブログにてこちらのコードを使用させて頂いてます。

    ブログ記事ごとにこの投票システムを設置しているのですが、よくある”人気順に記事を並べ替える”といったようなことを実現したいので、カウント数をファイルに書き込むと同時に、MySQLにもカウント数を格納しようと思っています。

    vote.phpに以下のようなコード加えてデータベースにカウント数を格納しようとしたのですが、OKの文字列がJavascriptに返らないようで、うまく動作しませんでした。

    ~前略~

    //カウントアップ
    $filename = “file/”.$file_id;
    $fp = @fopen($filename, “w”);
    flock($fp, LOCK_EX);
    fputs($fp, $count);
    flock($fp, LOCK_UN);
    fclose($fp);

    // カウント数をgoodフィールドに格納
    $sql = sprintf(‘INSERT posts SET good=good+%d WHERE id=%d’,
    mysql_real_escape_string($count),
    mysql_real_escape_string($file_id)
    );
    mysql_query($sql) or die(mysql_error());

    setcookie($cookie_name, $count, time()+10); // 10秒有効のクッキーを設定

    ~後略~

    ※$file_idには記事のidのみを当てるように変更してあります。

    コードは間違っていないと思うのですが、そもそもvote.phpでこのような処理はできないのものなのでしょうか?
    ちなみにブログシステムはPHP,MySQLで自作したものを使っています。

    場違いな質問かもしれませんが、もし解決策をご存知でしたらご教示いただけるとありがたいです。

    よろしくお願いいたします。

  7. nishi より:

    sakamotoさま

    再コメントありがとうございました。
    確認が遅くなりまして申し訳ございません。

    無事にうまく動いたとのことで良かったです。
    コメント削除とのことでしたが、いただきましたコメントは
    私の対応も含めて残しておきたいと思っておりますので
    何とぞご了承くださいませ。

  8. nishi より:

    三浦和紀さま

    コメントありがとうございます。
    私の方でもMySQLの処理を入れてみたのですが、特に問題なく動きました。
    SQLの記述の問題ではないかと思いましたので、
    詳細はメールにて送らせていただきます。
    よろしくお願いいたします。

  9. 三浦和紀 より:

    メールを確認いたしました。お忙しい中、ご検証とアドバイスを頂きありがとうございました。ご指摘頂いた通り、INSERT部分をUPDATEに変更したところ問題なく動作しました。初歩的なミスでした…

    それと、

    good=good+%d

    の部分は加算する必要がなかったんですね。

    good=%d

    に変更し、問題なくデータベースに格納することができました。

    おかげさまで次に進めそうです!
    本当に感謝しております。ありがとうございました!

  10. nishi より:

    三浦さま

    コメント&メールありがとうございました。
    問題なくデータベースへ登録できたとのことで良かったです。
    このブログが少しでもお役にたてたのでしたらうれしいです。

  11. nabe より:

    わかりやすく、有益なソースを公開していただき感謝します。

    図々しいのですが、こちらで試して難しかった点を質問させて頂きたく、ご連絡しました。

    カウントするオブジェクトを含むブロックを、phpのforeach文でループして書き出して使用したかったのですが、
    リロードする度にカウントがゼロに戻ってしまうのです。

    お時間ある際で結構ですので、どの辺りを修正すれば対応できそうか、ご教授頂けますか?

  12. nabe より:

    nabeです。先程の送信事項に補足です。

    ‘voteId’、’cntClass’、共に変数を読み込むように設定しています。
    リロードさえしなければ一見問題ないのですが、リロードしたりページを離脱して戻ると、
    カウントがゼロになってしまいます。

    尚、ループ文を使用せずに、全てのブロックを直接htmlで記述すれば問題なく動きます。

  13. nabe より:

    nabeです。何度もすみません。
    先程質問させて頂いた件、自己解決しましたのでご報告です。



    上記’voteId’の変数が、シングルコーテーションにより展開されない、
    という初心者にありがちなミスでした。

    何度もムダな投稿をしてしまい、申し訳ありませんでした。
    今後とも、どうぞ宜しくお願いいたします。

  14. nishi より:

    nabeさま

    コメントありがとうございます。返答が遅くなってしまいまして申し訳ありません。
    すでに自己解決されたとのことで、よかったです。
    この記事がお役に立てれば幸いです。

  15. kotubu より:

    はじめまして。大変有益なソースコードを提供をして頂きありがとうございます。
    コードを使い、テストをしているのですが、コメント11,12,13にあるように自分も同様に
    ‘voteId’、’cntClass’に変数を与え、foreachを使ってみたのですが、ロードしたりページを離脱して戻ると、カウントがゼロになってしまいます。
    コメント11,12,13は解決されたみたいなのですが、お時間が許すときで構いませんので、
    ご教授をいただけませんでしょうか?

  16. nishi より:

    kotubuさま

    コメントありがとうございます。
    以前のnabeさまのコメントにもありますが、PHPでのループ処理のところでの変数のつけ方あたりに問題があるのかな?と思っております。
    別途メールにてもご連絡させていただきましたので、よろしければソースをお送りください。
    よろしくお願いいたします。

  17. ino より:

    初めまして。
    こちらのページのコードを使用させていただき、ガールズチャンネル(http://girlschannel.net/topics/120577/)
    のようなコメントに対する「いいね」「だめね」みたいな機能を付けたいと思っております。

    しかし、Wordpressで使用した場合、nabe様やkotubu様が投稿されているような形で、リロードすると数値が0になってしまいます。
    Wordpressではなく、単純にサーバー上にindex.phpとしてアップロードした場合は正常に動作致します。

    Wordpressではこのソースコードは使用できないのでしょうか?
    超初心者なもので…
    図々しい質問で申し訳ありませんが、ご返答いただけますと幸いです。

  18. nishi より:

    inoさま

    コメントありがとうございます。
    メールもさせていただきましたが、一度WordPressでも検証して回答させていただきます。
    少しお待ちいただけますでしょうか。
    よろしくお願いいたします。

  19. Tomiyama より:

    わかりやすく、有益なソースを公開していただき感謝しております。ありがとうございます。超初心者の者で、ほとんどコピペをしています。上手く動作しなかったので図々しいのですが、ご連絡差し上げました。ボタンを押すとNaNと表示されてしまうため、恐らくカウントアップの点が上手く接続できていないのだと思います。
    上記にある

    ※投票のファイルを格納するフォルダ「file」を作成して、属性を書き込み可能にしてください。


    //カウントアップ
    $filename = “file/”.$file_id.”.cnt”;


    を参考にfileフォルダを作成し、サーバーにアップしたのですが、どうも何か足りないようです。また$file_id.cntの意味が友達と相談してもわかりませんでした。これはWindows環境でしか使えない拡張子なのでしょうか。
    わかり辛い質問になってしまいましたが、お時間ある際で結構ですので、お助け願えるとありがたいです。よろしくお願いします。

  20. nishi より:

    Tomiyamaさん

    コメントありがとうございます。
    ボタンを押すとNaNとのことなので、スクリプト側がうまく動いていないかもしれません。
    また.cntの拡張子に特に意味はなく、.txtでも動作します。
    ですのでWindwos以外の環境でも大丈夫です。

    詳細は別途でメールにてご連絡さしあげますので、よろしくお願いいたします。

  21. yamada より:

    お世話になっております。とてもわかりやすく示して頂いて大変感謝しております。
    ローカル環境にてwordpressによる通販サイトを制作しております。
    テスト環境の直下のものは(index.php)動作するのですが、
    個別ページの方(single.php)はNaNが帰ってきてしまいます。
    また、いずれもwordpressを介すとカウントがリセットされてしまいます。
    もしよろしければ、検証結果ございましたらお教え頂けませんでしょうか。
    何卒、よろしくお願い致します。

  22. yamada より:

    追記致します。
    何とか数値が返って来るようになりました。
    わたしの方の記述ミスだったと思います。。すみません。
    しかし、リロードするとカウントが戻ってしまいます。
    vote.phpの2行目「file_id」と3行目「count」、17行目「count」がUndefinedとなったのち、OKと表示されているのですが、これが原因でしょうか?
    また、fileまでのパスは、wordpress テーマフォルダの中に入れてはダメな感じでしょうか?
    重ね重ね申し訳ございません。。
    お手すきの際で、もし宜しければご教授願います・・

  23. yamada より:

    本当に度々申し訳ございません。
    只今自己解決致しました。。
    色々と乱発してしまって申し訳ございませんでした。
    xamppで構築していたのですが、テンプレートフォルダにfileを入れていた為、という初歩的なミスでした。。
    申し訳ございませんでした。

  24. nishi より:

    yamadaさま

    返答が遅くなりまして申し訳ありません。
    自己解決されたとのこと、ご報告ありがとうございました。
    この記事が少しでもお役にたちましたら幸いです。

  25. navihei より:

    とても、ためになるソースを公開して頂き、ありがとうございます。

    先の方のように、単独での、index.php、vote.php、fileフォルダでは、正常動作が確認できるのですが、smartyでのtemplteを使うと、投票数が無表示となっています。
    jsのパスは合っております。

    templte上では、{}用に{literal}{/literal}を利用しています。
    が何らかの処置が必要なのかと思うのですが、ご教示願えれば幸いです。

    現在は、xamppでのローカル環境で行ってあります。


    htdocs
    ∟ xyz
    ∟ vote.php
    index.php
    jsフォルダ
    fileフォルダ
    templatesフォルダ
    ∟ index.tpl

  26. nishi より:

    naviheiさま

    ブログをご覧いただき、書き込みありがとうございます。
    私自身、xampp環境やsmartyで試した実績がないため、動作に不備があるのかもしれないですが、
    {literal}{/literal}を使用されているとのことで、その中で何かテンプレートタグを使われてはいないでしょうか?

    投票数が無表示というのは一番最初のページアクセス時から何も表示されないのか、
    投票ボタンを押すと表示されないのか、NaNになるのか、、など
    もう少し詳細情報をいただけますと助かります。

    よろしくお願いいたします。

  27. navihei より:

    nishi様
    早速の返信有難うございます。

    通常ですと、ページアクセスした際に 「0」 と表示され、fileフォルダには投票後に、voteId1.cntやvoteId2.cntと作成されていますが、

    smartyを使ったテンプレートにて行う際には、ページアクセスした時点では、数字が無表示であり、この時点で fileフォルダ には、無名(拡張子のみ).cntが作成されます。

    投票しますと「NaN」と表示され、fileフォルダには、voteId1.cntやvoteId2.cntと作成されます。
    作成されたvoteId1.cntやvoteId2.cntには、「NaN」となっています。

    {literal}{/literal}タグの中は、jsなどの{}を利用する際に必要となり、テンプレートタグは使っておりません。

    以前の方のコメントでも、WordPressでの事が書かれていましたが、自己解決されておりますので、やはり、パスが原因なのではと考えます。

    お手数ではありますが、アドバイス願います。

  28. nishi より:

    naviheiさま

    返信遅くなりましてすみません。
    カウント用ファイルは作成されているようなので、PHPは問題ないが、
    Javascriptの部分でエラーが出ている気がしますね。

    smartyで試してみたいと思いますので、少しお時間いただけますでしょうか。
    よろしくお願いいたします。

  29. navihei より:

    nishi様

    お手数かけますが、よろしくお願い致します。

  30. 通りすがり より:

    naviheiさん

    横から失礼します。
    もしかしてですけど、
    「」
    上記div内に文字列を入れてたりしませんか?

    例えば
    「投票数:」
    といった具合です。

    自分がそれで同じ症状になりました。

  31. あかさ より:

    とても助かりました。

    もし、お聞かせいただけるようでしたら、
    1に投票する!
    投票数:

    のところ、

    1つ目は、voteId1(2箇所)とcntClass1(1箇所)で
    2つ目以降は、1,2,3,4….と、手動で変えていけば良いのですが、

    写真掲示板(BBS)とかに設置する場合、
    その写真の評価をしてもらうタイプのものなのですが、

    自動でvoteId(2箇所)cntClass(1箇所)の数字が、
    3箇所共通で数字を変更していかないといけないのですが、

    その場合どうすれば良いのでしょうか?

    「スレが立つたびに、ランダムに共通の数字が3箇所に入るようにすればいい」のはわかるのですが、どうすればいいかわかりません。

    教えていただけると助かります。すみません。無理を言います。

  32. あかさ より:

    すみません。自己解決しました。
    お騒がせしました。

  33. poo より:

    こちらの投票システムを使用させていただいていますが
    同時アクセスの部分で問題があり、ご相談させていただきたいです。

    コンタクトフォームからメールが送れなかったのですが
    メールでご協力いただけませんでしょうか?

    よろしくお願い致します。

  34. 伊波 ケン より:

    カウントの数字をクリックして再アクセスすると、数字が元の0の初期値に戻ってしまいます。
    カウント記録がのこらないので、残るようにするにはどうしたらよいでしょうか?

    あとPHPのほうで複数のクリック防ぐためにクリック期間を一周間ほど伸ばして防いでいます。


    どうぞよろしくおながいします

  35. イハ より:

    なんどもご質問して大変申し訳ありません。上の方は一投票で数がカウントされましたので問題点としては解決していますが。問題はカウントアップの為の記述をHTMLに格納していて。
    属性が呼び出されずでカウントアップに繋がらないのだと思いましたが。
    そのカウントアップの記述を上記のにもあります。fileを作成とありますが、それはフォルダーを作成してその中にテキストエディタか何かに書いて入れておくということでしょうか?


    このぶぶんの格納方法を教えていただけたらと思います。どう宜しくお願いします。

  36. 伊波 ケン より:

    イハと申しますメールアドレスまちがえてました。

    大変申し訳ありません

  37. nishi より:

    伊波さま、コメントありがとうございます。
    遅くなりましたがメールにて回答させていただきましたのでご確認ください。
    よろしくお願いいたします。

  38. 伊波 ケン より:

    nisshi様
    大変ご返事の回答頂きとても感謝いたします。

    もう少し質問させてください。
    私のindex.htmlをindex.phpに書き換えて
    そのindex.phpの中に以下の文をどこかに置いておくということでよいのでしょうか?



    又、fileフォルダーは中身が無くfileのみをfftpサーバーに置くという認識で正しいでしょうか?

    度々の質問で大変ご迷惑をおかけしています。
    どうぞ宜しくお願い申し上げます。
           
                           伊 波

Comment:

Trackback URL: