Voting System Youtube Style With jQuery & PHP

Voting system can be important part of any website, especially if you want to keep track of user ratings. Let’s create a cookie based voting system, similar to YouTube like & dislike buttons (Thumbs up & Thumbs down), which can be applied to any content.

Voting System

We will assign Unique ID(s) to each voting block, these Unique IDs will play important role here, we will be updating and inserting database records, and identifying user votes based on it. Let’s create a 4 columns table in MySql Database.

1
2
3
4
5
6
7
CREATE TABLE IF NOT EXISTS `voting_count` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `unique_content_id` VARCHAR(100) NOT NULL,
  `vote_up` INT(11) NOT NULL,
  `vote_down` INT(11) NOT NULL,
  PRIMARY KEY (`id`)
);

Style

This is our CSS, this should go within head tag or in a CSS file.

1
2
3
4
5
6
7
8
9
10
<style type="text/css">
/*voting style */
.voting_wrapper {display:inline-block;margin-left: 20px;}
.voting_wrapper .down_button {background: url(images/thumbs.png) no-repeat;float: left;height: 14px;width: 16px;cursor:pointer;margin-top: 3px;}
.voting_wrapper .down_button:hover {background: url(images/thumbs.png) no-repeat 0px -16px;}
.voting_wrapper .up_button {background: url(images/thumbs.png) no-repeat -16px 0px;float: left;height: 14px;width: 16px;cursor:pointer;}
.voting_wrapper .up_button:hover{background: url(images/thumbs.png) no-repeat -16px -16px;;}
.voting_btn{float:left;margin-right:5px;}
.voting_btn span{font-size: 11px;float: left;margin-left: 3px;}
</style>

HTML markup

Paste following HTML code in your page anywhere you want voting system to appear, I have inserted the code inside header <h3> — </h3>. Replace each block ID XXXXXXX with unique number or string, Unique ID should not match with each other.

1
2
3
4
5
6
7
8
9
10
<!-- voting markup -->
<div class="voting_wrapper" id="XXXXXXX">
    <div class="voting_btn">
        <div class="up_button">&nbsp;</div><span class="up_votes">0</span>
    </div>
    <div class="voting_btn">
        <div class="down_button">&nbsp;</div><span class="down_votes">0</span>
    </div>
</div>
<!-- voting markup end -->

jQuery

On page load, we will fetch vote counts from database into <span class="up_votes"></span> and <span class="up_down"></span> elements. Using jQuery.each() we can loop through each voting block to collect Unique IDs. These IDs are required to fetch vote counts for each voting block.
Since we need to fill two values here, it is good idea to fetch JSON data. (See vote_process.php for PHP json_encode() usage).
Take a look at code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//####### on page load, retrive votes for each content
$.each( $('.voting_wrapper'), function(){
   
    //retrive unique id from this voting_wrapper element
    var unique_id = $(this).attr("id");
   
    //prepare post content
    post_data = {'unique_id':unique_id, 'vote':'fetch'};
   
    //send our data to "vote_process.php" using jQuery $.post()
    $.post('vote_process.php', post_data,  function(response) {
   
            //retrive votes from server, replace each vote count text
            $('#'+unique_id+' .up_votes').text(response.vote_up);
            $('#'+unique_id+' .down_votes').text(response.vote_down);
        },'json');
});

jQuery Code below is triggered when user clicks Thumbs up or Thumbs down icon. We need to retrieve the class name of clicked element and compare whether vote is like or dislike, then we send Ajax request to vote_process.php using jQuery $.post() along with Unique ID and Vote type. Please go though each comment line in the code to understand the method clearly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
$(".voting_wrapper .voting_btn").click(function (e) {
   
    //get class name (down_button / up_button) of clicked element
    var clicked_button = $(this).children().attr('class');
   
    //get unique ID from voted parent element
    var unique_id   = $(this).parent().attr("id");
   
    if(clicked_button==='down_button') //user disliked the content
    {
        //prepare post content
        post_data = {'unique_id':unique_id, 'vote':'down'};
       
        //send our data to "vote_process.php" using jQuery $.post()
        $.post('vote_process.php', post_data, function(data) {
           
            //replace vote down count text with new values
            $('#'+unique_id+' .down_votes').text(data);
           
            //thank user for the dislike
            alert("Thanks! Each Vote Counts, Even Dislikes!");
           
        }).fail(function(err) {
       
        //alert user about the HTTP server error
        alert(err.statusText);
        });
    }
    else if(clicked_button==='up_button') //user liked the content
    {
        //prepare post content
        post_data = {'unique_id':unique_id, 'vote':'up'};
       
        //send our data to "vote_process.php" using jQuery $.post()
        $.post('vote_process.php', post_data, function(data) {
       
            //replace vote up count text with new values
            $('#'+unique_id+' .up_votes').text(data);
           
            //thank user for liking the content
            alert("Thanks! For Liking This Content.");
        }).fail(function(err) {
       
        //alert user about the HTTP server error
        alert(err.statusText);
        });
    }
   
});
//end

Process User Votes

Here’s our complete vote_process.php file. This PHP code retrieves Ajax POST variables from voting system page, and $_POST[“vote”] variable is used to determine what action should be performed next.

Since this is a cookie based voting, script sets a cookie after each user vote and prevents user from voting again until the cookie expires.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php
####### db config ##########
$db_username = 'xxxxx';
$db_password = 'xxxxx';
$db_name = 'xxxxx';
$db_host = 'localhost';
####### db config end ##########

if($_POST)
{
       
    ### connect to mySql
    $sql_con = mysqli_connect($db_host, $db_username, $db_password,$db_name)or die('could not connect to database');

    //get type of vote from client
    $user_vote_type = trim($_POST["vote"]);
   
    //get unique content ID and sanitize it (cos we never know).
    $unique_content_id = filter_var(trim($_POST["unique_id"]),FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH);
   
    //Convert content ID to MD5 hash (optional)
    $unique_content_id = hash('md5', $unique_content_id);
   
    //check if its an ajax request, exit if not
    if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
        die();
    }
   

    switch ($user_vote_type)
    {          
       
        ##### User liked the content #########
        case 'up':
           
            //check if user has already voted, determined by unique content cookie
            if (isset($_COOKIE["voted_".$unique_content_id]))
            {
                header('HTTP/1.1 500 Already Voted'); //cookie found, user has already voted
                exit(); //exit script
            }
           
            //get vote_up value from db using unique_content_id
            $result = mysqli_query($sql_con,"SELECT vote_up FROM voting_count WHERE unique_content_id='$unique_content_id' LIMIT 1");
            $get_total_rows = mysqli_fetch_assoc($result);
           
            if($get_total_rows)
            {
                //found record, update vote_up the value
                mysqli_query($sql_con,"UPDATE voting_count SET vote_up=vote_up+1 WHERE unique_content_id='$unique_content_id'");
            }else{
                //no record found, insert new record in db
                mysqli_query($sql_con,"INSERT INTO voting_count (unique_content_id, vote_up) value('$unique_content_id',1)");
            }
           
            setcookie("voted_".$unique_content_id, 1, time()+7200); // set cookie that expires in 2 hour "time()+7200".
            echo ($get_total_rows["vote_up"]+1); //display total liked votes
            break; 
       
        ##### User disliked the content #########
        case 'down':
           
            //check if user has already voted, determined by unique content cookie
            if (isset($_COOKIE["voted_".$unique_content_id]))
            {
                header('HTTP/1.1 500 Already Voted this Content!'); //cookie found, user has already voted
                exit(); //exit script
            }

            //get vote_up value from db using unique_content_id
            $result = mysqli_query($sql_con,"SELECT vote_down FROM voting_count WHERE unique_content_id='$unique_content_id' LIMIT 1");
            $get_total_rows = mysqli_fetch_assoc($result);
           
            if($get_total_rows)
            {
                //found record, update vote_down the value
                mysqli_query($sql_con,"UPDATE voting_count SET vote_down=vote_down+1 WHERE unique_content_id='$unique_content_id'");
            }else{
               
                //no record found, insert new record in db
                mysqli_query($sql_con,"INSERT INTO voting_count (unique_content_id, vote_down) value('$unique_content_id',1)");
            }
           
            setcookie("voted_".$unique_content_id, 1, time()+7200);  // set cookie that expires in 2 hour "time()+7200".
            echo ($get_total_rows["vote_down"]+1);//display total disliked votes
            break; 
       
        ##### respond votes for each content #########     
        case 'fetch':
            //get vote_up and vote_down value from db using unique_content_id
            $result = mysqli_query($sql_con,"SELECT vote_up,vote_down FROM voting_count WHERE unique_content_id='$unique_content_id' LIMIT 1");
            $row = mysqli_fetch_assoc($result);
           
            //making sure value is not empty.
            $vote_up    = ($row["vote_up"])?$row["vote_up"]:0;
            $vote_down  = ($row["vote_down"])?$row["vote_down"]:0;
           
            //build array for php json
            $send_response = array('vote_up'=>$vote_up, 'vote_down'=>$vote_down);
            echo json_encode($send_response); //display json encoded values
            break;

    }

}
?>

Download Demo

  1. Post comment submit button background orange font family name pleaseeeee

     Reply
  2. when i use as download it works perfectly.. but when i add it to my html it keeps saying already liked this content although i haven’t and numbers stay at zero. do you know how to fix it?

     Reply
  3. dude you are a legend!

     Reply
  4. Nice tutorial but if i clear the cookies i will be able to vote again.
    Do you have a tutorial which cannot be hacked .
    if i want to implement a like dislike system.
    which cannot be hacked
    how should i implement it
    1>ip based
    2>mac address based

     Reply
  5. Everything works except it doesn’t post to my mysql db. The database is set up correctly and the usernames passwords and all of that is correct but it doesn’t post anything. Why would that be?

     Reply
  6. Thanks for good example, saved me few hours of typing.
    Great website keep it up, thanks.

     Reply
  7. Is it possible to have several ratings on one page?

     Reply
  8. Hi,
    How can I create more like/dislike buttons than three?

     Reply
  9. Thank you very much for this tutorial .

     Reply
  10. Hello, Thank excellent tutorial, helped me a lot !!! keep it up

     Reply
  11. @Saran
    Can you make this script to save the users’ ip too because some in browsers the cookies are disabled

     Reply
  12. Thank you very much helped me to understand the logic of this explanation.

     Reply
  13. Hey, we have a forum website and we want to use a voting system for the messages and we want to source messages by most liked and most disliked. So we need some codes those linked to our database.
    How can we get like and dislike scripts to work with those messages. We are using php and mysql.
    Thanks…

     Reply
  14. Hi, I am trying to use it for a school project in which I’m putting togheter a social network kind of script, so far I’ve managed to put the voting sysment into the loop of the content I want to rate, but then when I try to vote with a different user it tells me I’ve already voted, My security is very simple I only have a $_SESSION with the id of the users, some how I think the way is ralting that into the voting system instead of the unique_content_id am I right? any rough ideas on how to that? I’m only a few months old on php and web programming by the way so if you think is too hard to explain I’ll understand.
    Cheers!

     Reply
  15. how would I customize this so there are four answers like a,b,c,d instead of vote up or down?

     Reply
  16. how would I customize this so there are four answers like a,b,c,d instead of vote up or down?

     Reply
  17. Unfortunately, this is easily exploitable for me with Google Chrome’s developer console. I simply vote, clear the cookie from the Resources tab, then vote again without error. This isn’t the best approach.

     Reply
    • I think the most accurate voting system would be the vote per registered user, or IP based voting which still has limitations. But if anyone can vote, I think the best approach would be just to thank user for voting and do not show any kind of errors such as “already voted!”.

    • In that case, someone could just run a macro script all day long and keep voting. I could easily run my macro software and get tens of thousands of votes a day ;-)

      I agree with the best approach being via registration. Its a lot more effort for someone to make another vote since they’d have to create a new account along with an e-mail address. That would definitely stop most people from even attempting it. Even though its not as user friendly, it gives a more accurate count.

      :)

  18. Thanks for posting this. Do you have a suggestion on a dynamic div id solution , I am trying to use this for a program that will output multiple dynamic items. Thanks in advance.

     Reply
    • I was able to figure it out. Again, thanks for the great post. How would you recommend tweaking this a little to provide a notification to the originating user. I am trying to build a user notification system with a voting system and need for once the vote is captured I need an additional record added. Thanks in advance.

  19. Hi Saran, This is a beautiful codes.
    But I can get the right value of votes

    1
    2
    3
    4
    5
    6
    7
    //retrive votes from server, replace each vote count text
    $('#'+unique_id+' .food-score-up').text(response.vote_up);
    $('#'+unique_id+' .food-score-down').text(response.vote_down);

    It only show "0" at my page
    &nbsp;
    0 <!-- IT KEEPS ZERO AND ZERO -->

    can you help me saran?

    Regards,
    Andhi

     Reply
  20. hi do you have any idea how to change the message in this header to UTF-8 format?
    header(‘HTTP/1.1 500 Already Voted this Content!’);
    because when i changed already voted this content message to chinese it showed random character..

     Reply
  21. YEAH!! I have been searching and learning about rating for almost 3 days at least 6 to 7 hours a day, tried lots of codes programming and stuff just get to this one and it worked perfectly Thank you very much.

     Reply
  22. Everything seems to be working perfectly but nothing is being posted in the database – assist please

     Reply
  23. HTML markup:
    What should I put in the ID?
    YOU CAN ADD THIS TO MY FACEBOOK PAGE?

     Reply
  24. i used these code. Everytime i clicked ‘like’ gives error ‘Method not allowed’. Can u give me answer for that?

     Reply
  25. is there a wordpress plugin ??.i need that one..

     Reply
  26. Hello Saran, thanks for the tutorials but I get errors like

    Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given in /Applications/MAMP/htdocs/ghalive.com/vote_process.php on line 45

    This error shows up when I like(thumbs up) a content or article and the record in the database table never updates. But the error never shows up when I dislike(thumbs down) a content or article.

    The dislike(thumbs down) record will show on the page when you dislike but will show 0 once you refresh the page. is there better way to correct this?

     Reply
    • try:

      1
      echo mysqli_error($sql_con);

      after mysqli_query, to view last mysql error.

    • Hi Saran, I can’t still figure where the problem is. I hope its just a small problem but can’t find it. The error I get is as follows:

      Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given in /Applications/MAMP/htdocs/live.com/vote_process.php on line 45

      The point is I don’t get this error when I dislike a content. Its shows me number of dislikes but once I refresh the page, everything comes back to zero. I only get the above error when I like a content.

      Can you please help me with it?

    • Error only appears when MySqli query returns empty or 0 (false), in this case make sure table name is correct, also check http://j.mp/12H4J9v I’ve just tested the sample code and could not find such errors in it.

    • Hi Saran, thanks a lot for your time. I tried the script and it works perfectly. But am trying to do change the database and change the field names in the code so I can use it on a music site but am having a little trouble. Below is the code:

      //PHP Code
      $like, ‘dislike’=>$dislike);
      echo json_encode($send_response); //display json encoded values
      break;

      }

      }
      ?>

      //JQuery Code
      $(document).ready(function() {

      //####### on page load, retrive votes for each content
      $.each( $(‘.voting_wrapper’), function(){

      //retrive music_id from this voting_wrapper element
      var music_id = $(this).attr(“id”);

      //prepare post content
      post_data = {‘music_id’:music_id, ‘vote’:’fetch’};

      //send our data to “vote_process.php” using jQuery $.post()
      $.post(‘vote_process.php’, post_data, function(response) {

      //retrive votes from server, replace each vote count text
      $(‘#’+music_id+’ .likes’).text(response.like);
      $(‘#’+music_id+’ .dislike’).text(response.dislike);
      },’json’);
      });

      //####### on button click, get user vote and send it to vote_process.php using jQuery $.post().
      $(“.voting_wrapper .voting_btn”).click(function (e) {

      //get class name (down_button / up_button) of clicked element
      var clicked_button = $(this).children().attr(‘class’);

      //get music_id from voted parent element
      var music_id = $(this).parent().attr(“id”);

      if(clicked_button===’down_button’) //user disliked the content
      {
      //prepare post content
      post_data = {‘music_id’:music_id, ‘vote’:’down’};

      //send our data to “vote_process.php” using jQuery $.post()
      $.post(‘vote_process.php’, post_data, function(data) {

      //replace vote down count text with new values
      $(‘#’+music_id+’ .dislike’).text(data);

      //thank user for the dislike
      alert(“Thanks! Each Vote Counts, Even Dislikes!”);

      }).fail(function(err) {

      //alert user about the HTTP server error
      alert(err.statusText);
      });
      }
      else if(clicked_button===’up_button’) //user liked the content
      {
      //prepare post content
      post_data = {‘music_id’:music_id, ‘vote’:’up’};

      //send our data to “vote_process.php” using jQuery $.post()
      $.post(‘vote_process.php’, post_data, function(data) {

      //replace vote up count text with new values
      $(‘#’+music_id+’ .likes’).text(data);

      //thank user for liking the content
      alert(“Thanks! For Liking This Content.”);
      }).fail(function(err) {

      //alert user about the HTTP server error
      alert(err.statusText);
      });
      }

      });
      //end

      });

      // HTML code

      <div class="voting_wrapper" id="”>

       0 Likes

       0 Dislikes

      Please let me know if there something am doing wrong. I really appreciate your help

    • Opps! Some parts of the codes is not showing. Is there a better way to send u the code?

  27. I really love your work it so clean to me :) but… i having small problem.
    After submiting vote UP or DOWN instead of count numbers it shows me full code line ” {“vote_up”:”1″,”vote_down”:”0″}”

     Reply
    • It has been fixed. by mistake i did delete code -> echo ($get_total_rows[“vote_up”]+1); //display total liked votes

  28. rather than have index.php can this work with index.html, even if it don’t return thank you for vote but the count.

     Reply
  29. thank you great article, isit free to use on clients website?

     Reply
Message Type : Question Comment ?
  • Question : Can include code, jsFiddle, codePen etc using Markdown Syntax.
  • Comment : Short comments and questions.