5 Star Rating system with jQuery, AJAX, and PHP

Star rating bar allows the user to submit his thoughts on whether the content or product is useful or not. This also gives the administrator a view how well its item is performing.

It is very common on the e-commerce websites.

In this tutorial, I am using jQuery Bar Rating plugin to display star rating on the screen.

Whenever the user changes the rating then send an AJAX request to save the user currently rating status on the MySQL database table with PHP.

5 Star Rating system with jQuery, AJAX, and PHP


Contents

  1. Table structure
  2. Configuration
  3. HTML & PHP
  4. CSS
  5. PHP
  6. Script
  7. Demo
  8. Conclusion

 


1. Table structure

I am using posts and post_rating table in the tutorial example.

posts table

CREATE TABLE `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `content` text NOT NULL,
  `link` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

post_rating table

CREATE TABLE IF NOT EXISTS `post_rating` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userid` int(11) NOT NULL,
  `postid` int(11) NOT NULL,
  `rating` int(2) NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

2. Configuration

Create a config.php for database connection.

Completed Code

<?php
$host = "localhost"; /* Host name */
$user = "root"; /* User */
$password = ""; /* Password */
$dbname = "tutorial"; /* Database name */

$con = mysqli_connect($host, $user, $password,$dbname);
// Check connection
if (!$con) {
 die("Connection failed: " . mysqli_connect_error());
}

3. HTML & PHP

You can download the plugin from here.

Load jQuery Bar Rating plugin script with jQuery library and also load a font awesome theme CSS with font awesome CDN file.

I have fixed the userid to 4 which you can replace with the $_SESSION variable. Fetch all records from the posts Table.

Get user rating on the post and average of the post.

Create a layout to show title and content.

Using <select> element to show the star rating on the screen. Defined data-id attribute to get element id on the selection in the script.

Set the previously selected rating by calling barrating() method where pass rating value on the set.

Completed Code

<?php include "config.php"; ?>

<!-- CSS -->
<link href="style.css" type="text/css" rel="stylesheet" />
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css">
<link href='jquery-bar-rating-master/dist/themes/fontawesome-stars.css' rel='stylesheet' type='text/css'>
 
<!-- Script -->
<script src="jquery.js" type="text/javascript"></script>
<script src="jquery-bar-rating-master/dist/jquery.barrating.min.js" type="text/javascript"></script>

<div class="content">

 <?php
 $userid = 4;
 $query = "SELECT * FROM posts";
 $result = mysqli_query($con,$query);
 while($row = mysqli_fetch_array($result)){
  $postid = $row['id'];
  $title = $row['title'];
  $content = $row['content'];
  $link = $row['link'];

  // User rating
  $query = "SELECT * FROM post_rating WHERE postid=".$postid." and userid=".$userid;
  $userresult = mysqli_query($con,$query) or die(mysqli_error());
  $fetchRating = mysqli_fetch_array($userresult);
  $rating = $fetchRating['rating'];

  // get average
  $query = "SELECT ROUND(AVG(rating),1) as averageRating FROM post_rating WHERE postid=".$postid;
  $avgresult = mysqli_query($con,$query) or die(mysqli_error());
  $fetchAverage = mysqli_fetch_array($avgresult);
  $averageRating = $fetchAverage['averageRating'];

  if($averageRating <= 0){
   $averageRating = "No rating yet.";
  }
 ?>
  <div class="post">
   <h1><a href='<?php echo $link; ?>' class='link' target='_blank'><?php echo $title; ?></a></h1>
   <div class="post-text">
    <?php echo $content; ?>
   </div>
   <div class="post-action">
   <!-- Rating -->
   <select class='rating' id='rating_<?php echo $postid; ?>' data-id='rating_<?php echo $postid; ?>'>
    <option value="1" >1</option>
    <option value="2" >2</option>
    <option value="3" >3</option>
    <option value="4" >4</option>
    <option value="5" >5</option>
   </select>
   <div style='clear: both;'></div>
   Average Rating : <span id='avgrating_<?php echo $postid; ?>'><?php echo $averageRating; ?></span>

   <!-- Set rating -->
   <script type='text/javascript'>
   $(document).ready(function(){
    $('#rating_<?php echo $postid; ?>').barrating('set',<?php echo $rating; ?>);
   });
   </script>
   </div>
  </div>
 <?php
 }
 ?>

</div>

4. CSS

.content{
 border: 0px solid black;
 border-radius: 3px;
 padding: 5px;
 margin: 0 auto;
 width: 50%;
}

.post{
 border-bottom: 1px solid black;
 padding: 10px;
 margin-top: 10px;
 margin-bottom: 10px;
}

.post:last-child{
 border: 0;
}

.post h1{
 font-weight: normal;
 font-size: 30px;
}

.post a.link{
 text-decoration: none;
 color: black;
}

.post-text{
 letter-spacing: 1px;
 font-size: 15px;
 font-family: serif;
 color: gray;
 text-align: justify;
}
.post-action{
 margin-top: 15px;
 margin-bottom: 15px;
}

.like,.unlike{
 border: 0;
 background: none;
 letter-spacing: 1px;
 color: lightseagreen;
}

.like,.unlike:hover{
 cursor: pointer;
}

5. PHP

Create a rating_ajax.php file.

Check for a postid entry by the user in post_rating Table. If a record exists then update the rating otherwise insert a new record.

Calculate average rating on the $postid and return JSON response.

Completed Code

<?php

include "config.php";

$userid = 4; // User id
$postid = $_POST['postid'];
$rating = $_POST['rating'];

// Check entry within table
$query = "SELECT COUNT(*) AS cntpost FROM post_rating WHERE postid=".$postid." and userid=".$userid;

$result = mysqli_query($con,$query);
$fetchdata = mysqli_fetch_array($result);
$count = $fetchdata['cntpost'];

if($count == 0){
 $insertquery = "INSERT INTO post_rating(userid,postid,rating) values(".$userid.",".$postid.",".$rating.")";
 mysqli_query($con,$insertquery);
}else {
 $updatequery = "UPDATE post_rating SET rating=" . $rating . " where userid=" . $userid . " and postid=" . $postid;
 mysqli_query($con,$updatequery);
}

// get average
$query = "SELECT ROUND(AVG(rating),1) as averageRating FROM post_rating WHERE postid=".$postid;
$result = mysqli_query($con,$query) or die(mysqli_error());
$fetchAverage = mysqli_fetch_array($result);
$averageRating = $fetchAverage['averageRating'];

$return_arr = array("averageRating"=>$averageRating);

echo json_encode($return_arr);

6. Script

Initialize barrating() on class='rating'. Define theme and onSelect option.

The onSelect triggers when star rating is been changed. Get the element id and split it to get the postid.

Send an AJAX request where pass postid and value variables as data.

On successful callback update the average value on the <span> element with the response.

Completed Code

$(function() {
 $('.rating').barrating({
  theme: 'fontawesome-stars',
  onSelect: function(value, text, event) {

   // Get element id by data-id attribute
   var el = this;
   var el_id = el.$elem.data('id');

   // rating was selected by a user
   if (typeof(event) !== 'undefined') {
 
     var split_id = el_id.split("_");
     var postid = split_id[1]; // postid

     // AJAX Request
     $.ajax({
       url: 'rating_ajax.php',
       type: 'post',
       data: {postid:postid,rating:value},
       dataType: 'json',
       success: function(data){
         // Update average
         var average = data['averageRating'];
         $('#avgrating_'+postid).text(average);
       }
     });
   }
  }
 });
});

7. Demo

Change star rating of the posts. View in a new tab.


8. Conclusion

I used jQuery Bar Rating plugin to implement star rating on the web page. You can use any other plugins for this.

In the demonstration, I have fixed the userid value which you can update with $_SESSION variable while implementing on your project.

If you found this tutorial helpful then don't forget to share.

Related Post

Spread the love
  • 1
  •  
  •  
  •  
  •  
  •  

13 Comments

  1. Meek said:

    Great work, thanks. One of the best solutions, I’ve found.
    One question: My sites is on a hosted server. I currently only have access to creating ONE database table. Can I somehow merge the two tables in your code? So that I have average vote and number of votes?
    Would that work?

    Kind regards.

    August 7, 2017
    Reply
    • Yogesh Singh said:

      You don’t need another table just to separate average and number of votes. You can easily do it with a single table by the use of the count of votes find the average which I am doing in the tutorial.

      August 7, 2017
      Reply
  2. Gordon said:

    Awesome tutorial Yogesh Singh, I will most definitley bookmark your website. This is exactly what I was looking for.

    I was wondering if you have any tutorials on how to track the page views of each page/post on my website. I want to display the views for each page/post and not the total views. I can’t seem to find this any tutorials that does this. All of them only display the total views. I would really appreciate it if you could point me in the right direction. Thanks for the awesome work you’re doing.

    September 12, 2017
    Reply
    • Yogesh Singh said:

      Hi Gordon,
      Currently, I don’t have a tutorial on this.
      I will try to publish a tutorial on this soon. Meanwhile, subscribe our newsletter to get notified.

      September 13, 2017
      Reply
  3. Besa said:

    Hello!

    Thanks a lot for this great tutorial, the best i have found!

    But I’m having a little problem and I really can’t figure out what’s wrong: it won’t take into consideration the vote I make if I click on a star… and doesn’t send the vote to the database.

    Otherwise, the average rating from the db is correct.

    January 8, 2018
    Reply
    • Yogesh Singh said:

      Hi Besa,
      I think there is an error in your AJAX file to check add error: function(data) in $.ajax request and if there is an error then it will display in browser console. According to it debug the code
      $.ajax({
      url: ‘likeunlike.php’,
      type: ‘post’,
      data: {postid:postid,rating:value},
      dataType: ‘json’,
      success: function(data){
      // Update average
      var average = data[‘averageRating’];
      $(‘#avgrating_’+postid).text(average);
      },
      error: function(data){
      console.log(“error : ” + JSON.stringify(data) );
      }
      });

      You can mail me your files at makitweb@gmail.com if the issue is not resolved.

      January 9, 2018
      Reply
  4. Akash Aher said:

    Awesome tutorial, thank you for helping so neatly

    February 11, 2018
    Reply
  5. webi said:

    Hello, nice tutorial. Just one question, How can I disable ratings? I mean I want to display ratings and do not allow user to submit their ratings from that page.

    May 14, 2018
    Reply
    • Yogesh Singh said:

      Add following script at the end of the page –

      $(document).ready(function(){
      $(‘.br-widget a’).unbind();
      });

      This script removes all events from the rating element.

      May 14, 2018
      Reply
  6. Staria said:

    Hi… you wouldn’t happen to have a version of this tutorial written for CodeIgniter, would ya? I can’t seem to find a decent CodeIgniter Rating tutorial.

    August 31, 2018
    Reply
    • Yogesh Singh said:

      Currently, I have not written the Rating tutorial for CodeIgniter. I will try to publish it soon.

      August 31, 2018
      Reply
  7. Danish Jamshed said:

    Hi I am getting .barrating is not a function error. do you have any idea about it ?

    September 26, 2018
    Reply
    • Yogesh Singh said:

      Hi Danish,
      I think jquery.barrating.min.js script is not included in your file that’s why you are viewing this error.

      September 26, 2018
      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *