食べログとか価格.comとか口コミサイトで見る「ナイス!」とか「参考になった!」などの自作いいね!ボタンをphpとajaxで実装する

2015.4.7 webツール

食べログとか価格.comとか口コミサイトで見る「ナイス!」とか「参考になった!」などの自作いいね!ボタンをphpとajaxで実装する

食べログとか口コミ系のサイトとかアフィリエイト系のLPでよく見かける「参考になった」などの、Facebookいいね系のボタン(なんて言ったらいいか判らないのですが)を自分で作ってみましょう。

今回はデータベースに格納せずに、任意の名前でファイルを生成して、クリックされる度にそこに書き込んでいく、という超簡易的なかたちで実装してみます。

自作いいね!ボタンを作る

まず、今回のサンプルのディレクトリ構成について。

・index.php(ボタンを表示するページ)
・function.php(得票数の表示用の関数)
・vote.php(投票の処理)
-・js/
 -clickCount.js(click数をカウントアップする処理)
-log/(空のディレクトリ)

こんな感じで行きましょう。
もちろん、適宜に応じて変えていただいて結構です。

自作いいね!ボタンのおおまかな仕組み

  1. index.php:ボタンがクリックされる
  2. clickCount.js:javascriptで処理が発生。
  3. vote.php:ボタンのdata属性を元に「ボタンの識別ID」「そのボタンをクリックした回数を表示する箇所」を、受け取る
  4. function.php:getVoteCount関数で、得票数を書き込んだファイルから、得票数を取得し、index.phpで表示。

という流れです!

自作いいね!ボタンの動き

<!--*****index.php-->     
<button class="letsVote" data-id="buttonID" data-numhtml="countNum1">
   <span class="countNum1"><?php echo getVoteCount('buttonID'); ?></span>人が、「良かった!」と言っています。
</button>
<!--/////index.php-->

letsVoteクラスの要素をクリックした時にカウントされるようにしましょう。なので、buttonのクラスはとりあえず「letsVote」としておいて、
そのbuttonタグにはdata属性でdata-iddata-numhtmlを指定します。

data-id

ボタン識別用の任意のID。これを利用して得票数を書き出したり読み出したりするので、重複はNGです!

data-numhtml

得票数を表示する場所のクラス名を指定します。
例の場合は「countNum1」の中に表示するので、data-numhtml=”countNum1″と書きます。

 

それでは、得票数を表示する関数を書きましょう。

得票数を表示するphp

 

//function.php

function getVoteCount($id){
//カウント数を書きだしてあるファイル名
$fileName = "log/" . $id . ".count";

//fopenでファイルを読み込む (読み込みモード)
$fp = @fopen($fileName , "r");

if($fp){
//カウント数書き込み済みのファイルの内容を取得
$vote = fgets($fp , 9182);
}else{
$vote = 0;
}

return $vote;
}

引数に、任意のIDを指定しますが、ここはbuttonのdata-idと同じ値を渡すようにしてください。

何をやっているか?

clickCount.jsでカウントアップして、vote.phpで数を書き込んだファイルを、log/まで取りに行ってくる処理です。

fopen
$fp = @fopen($fileName , "r");

ファイルを開きます。
第一引数にファイルへのパス、第二引数に読み込みのモードを指定します。
今回の場合は「r」とかいてありますが、「読み込み限定」ということになります。

fgets
$vote = fgets($fp , 9182);

ファイルポインタから一行取得します。
第一引数にはfopenで返された「ファイルポインタ」を指定し、第二引数に取得する「長さ」を指定します。
省略した場合、行末まで取得。

クリックでカウントアップするJavascript

$(function(){

     $('.letsVote').on('click' , function(){
          
          $this = $(this);
          var id = $this.data("id"); //識別用ID(重複NG)
          var numHtml = "." + $this.data("numhtml"); //カウント数を表示するHTML
          var nowCount = Number($(numHtml).html()); //現在のカウント数
          var newCount = nowCount + 1;

          $.ajax({
               type : "POST",
               url : "vote.php",
               data: {
                    "file_id" : id,
                    "count" : newCount
               }
          }).done(function(data , datatype){
                    //送信先のvote.phpから、Completeが返ってきたらカウント更新
                    if(data == "Complete"){
                         $(numHtml).html(newCount);
                    }else{
                         alert("押しすぎ(´・ω・`)");
                    }
               }).fail(function(XMLHttpRequest, textStatus, errorThrown) {
                      $("#XMLHttpRequest").html("XMLHttpRequest : " + XMLHttpRequest.status);
                      $("#textStatus").html("textStatus : " + textStatus);
                      $("#errorThrown").html("errorThrown : " + errorThrown.message);
                  });
    });
});

なにをやっているか?

クラスletsVoteを指定したオブジェクトをクリックした際に発動する処理です。
ここで後のvote.phpに値を渡します。その値はbuttonのdata属性から引いてくるので、正しく指定したいですね。

$.ajax
$.ajax({
           type : "POST",
           url : "vote.php",
           data: {
                "file_id" : id,
                "count" : newCount
           }
        })
.done(function(){})
.fail(function(){});

ここで、POSTメソッドを使って、得票数の書き込みを行うvote.phpに、クリックされたボタンと現在の得票数を送信します。

$.ajaxの他のパラメータについては、とほほのjQuery入門にとても詳しく書いてあるのでぜひとも目を通してみてください!

done

通信が成功した場合の処理はdone(function(){~~~})の中に記述します。
success:でもいいのですが、jQuery1.8以降は「done」を使うようにしましょう。

この中で、「data」という引数を渡しています。
これは、$.ajaxの「url」で指定したファイルが返す値です。

あとでソースを記載しますが、”Complete“というテキストを返しているので(今回の場合はechoで)、urlで指定したファイルとの通信が成功した場合、doneの中のfunction(data)には「Complete」が入っていることになりますね。

vote.phpでは、超短時間での連続投票を禁止するためにCookieを記録させますので、Cookieの有効期限内である場合はCompleteが返らず、そのあとのif(){~~}に当てはまらないので、else{}の処理となります。
elseには書き込めなかった旨を書いたアラートを表示することにしましょう。

fail

doneの逆で、通信が失敗したときの処理です。

得票数を表示するphp

 

//vote.php

//////ajaxデータを受信1
$file_id = $_POST["file_id"]; //ファイル名
$count = $_POST["count"]; //投票数
$cookieName = "vote_" . $file_id; //クッキー名。
$cookieTime = time() + 10; //クッキーの有効期限(投票を制限する秒数)

///////クッキーが有効
if(isset($_COOKIE[$cookieName])){
     echo "クッキー制御により投票不可です。";

}else{
///////クッキーが無効=カウントアップ
     $count = $_POST["count"]; //投票数

     //カウント数を書き出すファイル名
     $fileName = "log/" . $file_id . ".count";

     $fp = @fopen($fileName , "w"); //書き込みモードで開く
     
     flock($fp , LOCK_EX); //排他的ロック(書く準備) 他のロックをすべてブロック
     fputs($fp , $count); //カウント数を書き込み
     flock($fp , LOCK_UN); //ロック開放
     fclose($fp);

     setcookie($cookieName , $count , $cookieTime); //10秒有効のクッキーをセット

     echo "Complete"; //clickCount.jsにはここの値を返す
}

なにをやっているか?

この「vote.php」は、ボタンを表示しているファイルからは直接読み込まれず、clickCount.jsでAjaxでデータの処理先として指定される以外は特に仕事をしません。
clickCount.jsはbuttonのdata属性から値を引いてきて、そこに関連付けられた情報(現在の得票数、クリックされたボタン=ID)をvote.phpに渡します。

$fileName = “log/” . $file_id . “.count”;
//vote.php
$fileName = "log/" . $file_id . ".count";

この変数$fileNameは、カウント数の書き出し用ファイルのパスとして使われます。

冒頭で説明しましたが、logというディレクトリですね。$file_idは、buttonの「data-id=””」で指定された「ボタンごとの識別用ID」なのですが、この値がファイル名となりカウント数が書きだされます。

拡張子は.countとかいうワケのわからないファイルですが.textでもいいです。変更する場合は、カウント数を取得して表示するfunction.phpの中の記述も変更してください。これを忘れると表示ができませんー!

//function.php
//カウント数を書きだしてあるファイル名
$fileName = "log/" . $id . ".count";
$file_id / $count

clickCount.jsの$.ajaxでPOSTメソッドで送信した値をこちらで受け取っています。

flock
     flock($fp , LOCK_EX); //排他的ロック(書く準備) 他のロックをすべてブロック
     flock($fp , LOCK_UN); //ロック開放

ここでは、ファイルのロック、ロック解除を行っています。

第一引数にはfopenで得たファイルポインタリソースを。第二引数にはロックの種類を指定します。

この「ロック」の概念については、ファイルロックをする【PHP】 – Programming Magicに詳しく書いてあります。

PHP: flock - Manual
fputs
 fputs($fp , $count); //カウント数を書き込み

第一引数のファイルに、第二引数の文字列を書き込みます。
なので今回は$countつまり得票数を書き込むことで保存しています。

fwrite()と同義なので、参考は以下。

PHP: fwrite - Manual
fclose()
     fclose($fp);

fopenされたファイルポインタを閉じます。

PHP: fclose - Manual
setcookie
 setcookie($cookieName , $count , $cookieTime); //10秒有効のクッキーをセット

$cookieTimeには、time()と10を足した値が入っています。
これは現在時刻から10秒間先を有効期限としたcookieを保存させることで、超短時間での連続投票を禁止するためです。

$countは、$_POST[“count”]; で取得した得票数です!

関数ファイル、javascriptファイルを読み込む

index.phpに、clickCount.jsとfunction.phpを読み込ませます。vote.phpは、clickCount.jsからajax通信で処理を渡すだけなのでindex.phpから読み込む必要はありません!

<!--*****index.php-->     
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="js/clickCount.js"></script>

//include
include_once(dirname(__FILE__) . 'fucntion.php');
//include

<button class="letsVote" data-id="buttonID" data-numhtml="countNum1">
   <span class="countNum1"><?php echo getVoteCount('buttonID'); ?></span>人が、「良かった!」と言っています。
</button>
<!--/////index.php-->
自作いいね!ボタンのデモ

いかがでしょうか。

超簡易的なのでちょっとあれですが、LPとかには使えると思います!

あとはjavascriptでクラス付与したりjQueryのanimateメソッドで面白いエフェクトを付けても良いと思います!

今回はこちらを参考にさせていただきましたー!

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

 

 

でわ!

Profile

東京でWebデザイナー・コーダーとして、フロントエンド的なことからデザイン思考的なことを考えたりして、ごにょごにょと活動中。(ポートフォリオ)Webクリエイターでは珍しい(?) HIPHOP, R&B好き。休日はよくカフェや漫画喫茶に出向いたりパン屋に行ったりコーヒ豆買いに行ったり、主に散歩しています。。デザインのトレンドやデザイン思考、HTML、CSSからSASS、Javascript、Wordpress構築などコーディングのTIPSなどをブログにアップしていきます。その他のことはtwitter( @satohmsys )まで。コーヒー友達募集中。