Skip to main content

Build Star Rating System with jQuery, PHP & MySQL

In our previous tutorial, we have explained how to develop User Registration and Login System with PHP & MySQL. In this tutorial, we will explain how to develop Star Rating System with jQuery, PHP & MySQL.

Star Rating System is a special feature of web applications to allow users to rate the services, products etc. It allows the owner to understand their customers preference to improve the quality of product or services.

Here in this tutorial we will create star rating system with logged in user feature to rate products by genuine users. The star rating system with PHP and MySQL script is easy to integrate into any kind of website to add rating feature.

Also, read:

You need to download star rating project file zip file to get all files and database tables using in this tutorial. The download link is at the end of tutorial.

So let’s implement star rating system with jQuery, PHP & MySQL. The major files are:

  • Index.php: List product with rating
  • rating.php: File to display product rating details.
  • rating_action.php: Perform actions related to rating.
  • rating.js: Handle front end actions related to rating.
  • Rating.php: A class that hold methods related to rating system.

Step1: Create MySQL Database Table

First we will create MySQL database tables to implement star rating system. We will create MySQL database table rating_users to store users login details to allow product rating.

CREATE TABLE `rating_users` (
  `userid` int(11) NOT NULL,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `avatar` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

We will create MySQL database table product to store product details to list and allow rating .

CREATE TABLE `product` (
  `id` int(11) NOT NULL,
  `name` varchar(256) NOT NULL,
  `description` text NOT NULL,
  `price` int(255) NOT NULL,
  `image` varchar(255) NOT NULL,
  `created` timestamp NOT NULL DEFAULT current_timestamp(),
  `modified` timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

We will create MySQL database table rating to product rating details.

CREATE TABLE `rating` (
  `ratingId` int(11) NOT NULL,
  `itemId` int(11) NOT NULL,
  `userId` int(11) NOT NULL,
  `ratingNumber` int(11) NOT NULL,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `comments` text COLLATE utf8_unicode_ci NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '1 = Block, 0 = Unblock'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Step2: List Product with Rating Details

In index.php file, we will implement functionality to display products with its rating details. We will call rating method getProductList() to get product details with rating and list them.

<div class="container">		
	<h2>Example: Advance Star Rating System with Ajax, PHP and MySQL</h2>
	<?php
	include 'inc/menu.php';
	include 'class/Rating.php';
	$rating = new Rating();
	$productList = $rating->getProductList();
	foreach($productList as $product){
		$average = $rating->getRatingAverage($product["id"]);
	?>	
	<div class="row">
		<div class="col-sm-4">
			<img class="product_image" src="image/<?php echo $product["image"]; ?>" style="width:350px;height:250px;padding-top:10px;">
		</div>
		<div class="col-sm-4">
		<h4 style="margin-top:10px;"><?php echo $product["name"]; ?></h4>
		<div><span class="average"><?php printf('%.1f', $average); ?> <small>/ 5</small></span> <span class="rating-reviews"><a href="rating.php?item_id=<?php echo $product["id"]; ?>">Rating & Reviews</a></span></div>
		<?php echo $product["description"]; ?>		
		</div>		
	</div>
	<?php } ?>	
</div>	

Step3: Implement Product Rating Functionality

In rating.php file, we will create form to submit product rating. When user go for submitting product rating, user will be asked for login to submit product rating.

<div id="ratingSection" style="display:none;">
	<div class="row">
		<div class="col-sm-12">
			<form id="ratingForm" method="POST">					
				<div class="form-group">
					<h4>Rate this product</h4>
					<button type="button" class="btn btn-warning btn-sm rateButton" aria-label="Left Align">
					  <span class="glyphicon glyphicon-star" aria-hidden="true"></span>
					</button>
					<button type="button" class="btn btn-default btn-grey btn-sm rateButton" aria-label="Left Align">
					  <span class="glyphicon glyphicon-star" aria-hidden="true"></span>
					</button>
					<button type="button" class="btn btn-default btn-grey btn-sm rateButton" aria-label="Left Align">
					  <span class="glyphicon glyphicon-star" aria-hidden="true"></span>
					</button>
					<button type="button" class="btn btn-default btn-grey btn-sm rateButton" aria-label="Left Align">
					  <span class="glyphicon glyphicon-star" aria-hidden="true"></span>
					</button>
					<button type="button" class="btn btn-default btn-grey btn-sm rateButton" aria-label="Left Align">
					  <span class="glyphicon glyphicon-star" aria-hidden="true"></span>
					</button>
					<input type="hidden" class="form-control" id="rating" name="rating" value="1">
					<input type="hidden" class="form-control" id="itemId" name="itemId" value="<?php echo $_GET['item_id']; ?>">
					<input type="hidden" name="action" value="saveRating">
				</div>		
				<div class="form-group">
					<label for="usr">Title*</label>
					<input type="text" class="form-control" id="title" name="title" required>
				</div>
				<div class="form-group">
					<label for="comment">Comment*</label>
					<textarea class="form-control" rows="5" id="comment" name="comment" required></textarea>
				</div>
				<div class="form-group">
					<button type="submit" class="btn btn-info" id="saveReview">Save Review</button> <button type="button" class="btn btn-info" id="cancelReview">Cancel</button>
				</div>			
			</form>
		</div>
	</div>		
</div>

In rating.js file, we will handle form submit and make ajax request to rating_action.php file with action saveRating to save product rating.

$('#ratingForm').on('submit', function(event){
	event.preventDefault();
	var formData = $(this).serialize();
	$.ajax({
		type : 'POST',
		dataType: "json",	
		url : 'rating_action.php',					
		data : formData,
		success:function(response){
			if(response.success == 1) {
				$("#ratingForm")[0].reset();
				window.location.reload();
			}
		}
	});		
});

In rating_action.php file, we will handle product rating save functionality by calling method saveRating().

if(!empty($_POST['action']) && $_POST['action'] == 'saveRating' 
	&& !empty($_SESSION['userid']) 
	&& !empty($_POST['rating']) 
	&& !empty($_POST['itemId'])) {
		$userID = $_SESSION['userid'];	
		$rating->saveRating($_POST, $userID);	
		$data = array(
			"success"	=> 1,	
		);
		echo json_encode($data);		
}

We will implement method saveRating() in class Rating.php.

public function saveRating($POST, $userID){		
	$insertRating = "INSERT INTO ".$this->ratingTable." (itemId, userId, ratingNumber, title, comments, created, modified) VALUES ('".$POST['itemId']."', '".$userID."', '".$POST['rating']."', '".$POST['title']."', '".$POST["comment"]."', '".date("Y-m-d H:i:s")."', '".date("Y-m-d H:i:s")."')";
	mysqli_query($this->dbConnect, $insertRating);	
}

Step4: View Product Rating

In rating.php file, we will implement functionality to display product star rating using method getProductRating() and method getRatingAverage()

<div id="ratingDetails"> 		
	<div class="row">			
		<div class="col-sm-3">				
			<h4>Rating and Reviews</h4>
			<h2 class="bold padding-bottom-7"><?php printf('%.1f', $average); ?> <small>/ 5</small></h2>				
			<?php
			$averageRating = round($average, 0);
			for ($i = 1; $i <= 5; $i++) {
				$ratingClass = "btn-default btn-grey";
				if($i <= $averageRating) {
					$ratingClass = "btn-warning";
				}
			?>
			<button type="button" class="btn btn-sm <?php echo $ratingClass; ?>" aria-label="Left Align">
			  <span class="glyphicon glyphicon-star" aria-hidden="true"></span>
			</button>	
			<?php } ?>				
		</div>
		<div class="col-sm-3">
			<?php
			$fiveStarRatingPercent = round(($fiveStarRating/5)*100);
			$fiveStarRatingPercent = !empty($fiveStarRatingPercent)?$fiveStarRatingPercent.'%':'0%';	
			
			$fourStarRatingPercent = round(($fourStarRating/5)*100);
			$fourStarRatingPercent = !empty($fourStarRatingPercent)?$fourStarRatingPercent.'%':'0%';
			
			$threeStarRatingPercent = round(($threeStarRating/5)*100);
			$threeStarRatingPercent = !empty($threeStarRatingPercent)?$threeStarRatingPercent.'%':'0%';
			
			$twoStarRatingPercent = round(($twoStarRating/5)*100);
			$twoStarRatingPercent = !empty($twoStarRatingPercent)?$twoStarRatingPercent.'%':'0%';
			
			$oneStarRatingPercent = round(($oneStarRating/5)*100);
			$oneStarRatingPercent = !empty($oneStarRatingPercent)?$oneStarRatingPercent.'%':'0%';
			
			?>
			<div class="pull-left">
				<div class="pull-left" style="width:35px; line-height:1;">
					<div style="height:9px; margin:5px 0;">5 <span class="glyphicon glyphicon-star"></span></div>
				</div>
				<div class="pull-left" style="width:180px;">
					<div class="progress" style="height:9px; margin:8px 0;">
					  <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="5" aria-valuemin="0" aria-valuemax="5" style="width: <?php echo $fiveStarRatingPercent; ?>">
						<span class="sr-only"><?php echo $fiveStarRatingPercent; ?></span>
					  </div>
					</div>
				</div>
				<div class="pull-right" style="margin-left:10px;"><?php echo $fiveStarRating; ?></div>
			</div>
			
			<div class="pull-left">
				<div class="pull-left" style="width:35px; line-height:1;">
					<div style="height:9px; margin:5px 0;">4 <span class="glyphicon glyphicon-star"></span></div>
				</div>
				<div class="pull-left" style="width:180px;">
					<div class="progress" style="height:9px; margin:8px 0;">
					  <div class="progress-bar progress-bar-primary" role="progressbar" aria-valuenow="4" aria-valuemin="0" aria-valuemax="5" style="width: <?php echo $fourStarRatingPercent; ?>">
						<span class="sr-only"><?php echo $fourStarRatingPercent; ?></span>
					  </div>
					</div>
				</div>
				<div class="pull-right" style="margin-left:10px;"><?php echo $fourStarRating; ?></div>
			</div>
			<div class="pull-left">
				<div class="pull-left" style="width:35px; line-height:1;">
					<div style="height:9px; margin:5px 0;">3 <span class="glyphicon glyphicon-star"></span></div>
				</div>
				<div class="pull-left" style="width:180px;">
					<div class="progress" style="height:9px; margin:8px 0;">
					  <div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="3" aria-valuemin="0" aria-valuemax="5" style="width: <?php echo $threeStarRatingPercent; ?>">
						<span class="sr-only"><?php echo $threeStarRatingPercent; ?></span>
					  </div>
					</div>
				</div>
				<div class="pull-right" style="margin-left:10px;"><?php echo $threeStarRating; ?></div>
			</div>
			<div class="pull-left">
				<div class="pull-left" style="width:35px; line-height:1;">
					<div style="height:9px; margin:5px 0;">2 <span class="glyphicon glyphicon-star"></span></div>
				</div>
				<div class="pull-left" style="width:180px;">
					<div class="progress" style="height:9px; margin:8px 0;">
					  <div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="2" aria-valuemin="0" aria-valuemax="5" style="width: <?php echo $twoStarRatingPercent; ?>">
						<span class="sr-only"><?php echo $twoStarRatingPercent; ?></span>
					  </div>
					</div>
				</div>
				<div class="pull-right" style="margin-left:10px;"><?php echo $twoStarRating; ?></div>
			</div>
			<div class="pull-left">
				<div class="pull-left" style="width:35px; line-height:1;">
					<div style="height:9px; margin:5px 0;">1 <span class="glyphicon glyphicon-star"></span></div>
				</div>
				<div class="pull-left" style="width:180px;">
					<div class="progress" style="height:9px; margin:8px 0;">
					  <div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="1" aria-valuemin="0" aria-valuemax="5" style="width: <?php echo $oneStarRatingPercent; ?>">
						<span class="sr-only"><?php echo $oneStarRatingPercent; ?></span>
					  </div>
					</div>
				</div>
				<div class="pull-right" style="margin-left:10px;"><?php echo $oneStarRating; ?></div>
			</div>
		</div>		
		<div class="col-sm-3">
			<button type="button" id="rateProduct" class="btn btn-info <?php if(!empty($_SESSION['userid']) && $_SESSION['userid']){ echo 'login';} ?>">Rate this product</button>
		</div>		
	</div>
	<div class="row">
		<div class="col-sm-7">
			<hr/>
			<div class="review-block">		
			<?php
			$productRating = $rating->getProductRating($_GET['item_id']);
			foreach($productRating as $rating){				
				$date=date_create($rating['created']);
				$reviewDate = date_format($date,"M d, Y");						
				$profilePic = "profile.png";	
				if($rating['avatar']) {
					$profilePic = $rating['avatar'];	
				}
			?>				
				<div class="row">
					<div class="col-sm-3">
						<img src="image/userpics/<?php echo $profilePic; ?>" class="img-rounded user-pic">
						<div class="review-block-name">By <a href="#"><?php echo $rating['username']; ?></a></div>
						<div class="review-block-date"><?php echo $reviewDate; ?></div>
					</div>
					<div class="col-sm-9">
						<div class="review-block-rate">
							<?php
							for ($i = 1; $i <= 5; $i++) {
								$ratingClass = "btn-default btn-grey";
								if($i <= $rating['ratingNumber']) {
									$ratingClass = "btn-warning";
								}
							?>
							<button type="button" class="btn btn-xs <?php echo $ratingClass; ?>" aria-label="Left Align">
							  <span class="glyphicon glyphicon-star" aria-hidden="true"></span>
							</button>								
							<?php } ?>
						</div>
						<div class="review-block-title"><?php echo $rating['title']; ?></div>
						<div class="review-block-description"><?php echo $rating['comments']; ?></div>
					</div>
				</div>
				<hr/>					
			<?php } ?>
			</div>
		</div>
	</div>	
</div>

We will implement method getProductRating() in class Rating.php.

public function getProductRating($itemId){
	$sqlQuery = "
		SELECT r.ratingId, r.itemId, r.userId, u.username, u.avatar, r.ratingNumber, r.title, r.comments, r.created, r.modified
		FROM ".$this->ratingTable." as r
		LEFT JOIN ".$this->ratingUsersTable." as u ON (r.userid = u.userid)
		WHERE r.itemId = '".$itemId."'";
	return  $this->getData($sqlQuery);		
}

We will also implement method getRatingAverage() in class Rating.php.

public function getRatingAverage($itemId){
	$itemRating = $this->getProductRating($itemId);
	$ratingNumber = 0;
	$count = 0;		
	foreach($itemRating as $itemRatingDetails){
		$ratingNumber+= $itemRatingDetails['ratingNumber'];
		$count += 1;			
	}
	$average = 0;
	if($ratingNumber && $count) {
		$average = $ratingNumber/$count;
	}
	return $average;	
}

You may also like:

You can view the live demo from the Demo link and can download the source from the Download link below.
Demo Download