How to create a PHP rating system

How to create a PHP rating system


In this tutorial I will show you how to create a php rating system for images, although this technique can be applied to anything.

In many websites, you will see rating systems in comments, content, images etc. Rating systems can be extremely useful as they can allow your users to see at a glance the quality of what they will be viewing before ever glancing on a page.

They can also allow you to let your users control content on your website, similar to how Digg.com decides what goes on their homepage with 'Diggs'. Essentially this is a very basic but effective comment system.

For this tutorial I will show you how to create a simple rating system for use with an image gallery. My next tutorial will be how to create the actual image gallery, so keep a look out for that.

I will go through this tutorial as I usually do, pretending that you have no experience in any of the necessary technologies and going through each line of code step by step. Although I will not spend too much time explaining the HTML code as there are plenty of places for this on the web.

That being said, it would help if you had experience in the following technologies:
- PHP
- MySQL (Relational Databases)
- HTML

This tutorial will use 3 files:
- gallery.php
- rate.php

Database
Firstly, we need to set up the table which will hold our image information. Go to your database and insert the following SQL:

CREATE TABLE IF NOT EXISTS `images` (
`imageID` int(11) NOT NULL auto_increment,
`imageURL` varchar(255) NOT NULL,
PRIMARY KEY (`imageID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;


We also need a table to hold our ratings, insert this SQL also:

CREATE TABLE IF NOT EXISTS `ratings` (
`ratingID` int(11) NOT NULL auto_increment,
`imageID` int(11) NOT NULL,
`rating` int(1) NOT NULL,
`ip` varchar(15) NOT NULL,
PRIMARY KEY (`ratingID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;


We set up 2 separate tables so that we can have more than one rating per image, and if you need to delete any ratings for any reason it will not mess up anything else. We want these tables to be linked, this is done through PHP later but I will just explain briefly. In the image table you will see the column named 'imageID' this is the primary key for this table. The primary key is simply a unique identifier to reference each item, it's much cleaner than having to reference each image by 'IMG_01.jpg' where especially with user driven content you have the danger of getting duplicate results. You will also see 'imageID' in the ratings table, this is what is called a 'foreign key' and is simply used to show which rating is linked to which image!

Phew! If at any point you need me to explain more in depth, simply leave a comment at the bottom and I will aim to get back to you within 24 hours.

Inserting Data
Now that we have our database set up, we need to put in an image so that we have something to use, we shall use HowHealthyIsMyDrink.com logo for this example feel free to use it for testing purposes but you can use anything, make sure you only use images you have the copyright to or you might get in trouble! :)

To insert the image information into the database you will need to run the following query:

INSERT INTO images (imageURL) VALUES ('http://www.howhealthyismydrink.com/images/logo.png');


Now we are good to go with the rating system.

Creating the gallery page
I am going to create a simple page without any styling, just for the purpose of this tutorial, feel free to edit and add style. The page will list the images from the database, will show its current rating and then will have a drop down box and a button for other users to rate it.

gallery.php - part 1
For the first part of this page I will simply layout the html markup, in the second part i will add the php code. Here is the very basic markup for the gallery page:

<html>
<head>
<title>My First Rating System</title>
</head>
<body>
<img src="" /><br />
<form id="ratethis" action="rate.php" method="post" >
<label for="Rating">Rate this image: </label>
<select name="rating">
<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>
<input type="submit" value="Rate this!" />
</form>
</body>
</html>


This will simply create a page with one image on and a little drop down box next to it with a 'Rate this!' button. I can't stress enough that these will need styling with css or they will look terrible :) I won't cover it in this tutorial though.

gallery.php - part 2
Now we will edit this code slightly to incorporate a php database loop to grab all of our images.

First thing we need to change is to pop all the code into a loop and query the database, the comments (//) will explain what is happening at each line.

<html>
<head>
<title>My First Rating System</title>
</head>
<body>
<?php
//DATABASE CONNECTION GOES HERE

$imageQuery = mysql_query("SELECT * FROM images"); //here we query the database for all the images
while($getImages = mysql_fetch_array($imageQuery)){ //now we loop through each of the rows returned from the query above and for each, we do the following code
$imageID = $getImages["imageID"]; //get the image ID from the database
$imageURL = $getImages["imageURL"]; //get the image URL from the database

//
//After this I break out of the php code so I will explain what is happening below, here.
//<img src="<?=$imageURL?>" /> Here we print the images URL from php inside the image src statement to display the image
//<form id="ratethis-<?=$imageID?>" This is simply to give each form a unique identifier, if the imagesID is 1 this will appear as "ratethis-1"
//action="rate.php?id=<?=$imageID?>" This will send the ID of the image to our php function
//
?>
<img src="<?=$imageURL?>" /><br />
<form id="ratethis-<?=$imageID?>" action="rate.php?id=<?=$imageID?>" method="post" >
<label for="Rating">Rate this image: </label>
<select name="rating">
<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>
<input type="submit" value="Rate this!" />
</form>
<?php
}
?>
</body>
</html>


Calculating the rating
As well as the code above, we also need to display and calculate the images current rating, to do this we insert the following php function after '<img src="<?=$imageURL?>" /><br />'

$rating_runningtotal = 0;
$ratingsQuery = mysql_query("SELECT * FROM ratings WHERE imageID='$imageID'"); //query the database for all ratings which are related to this image.
$numberOfRatings = mysql_num_rows($ratingsQuery); //get the number of ratings this image has
while($getRatings = mysql_fetch_array($ratingsQuery)){ //loop through each rating
$rating = $getRatings["rating"]; //get the actual rating and assign it to a variable
$rating_runningtotal = $rating_runningtotal + $rating; //add the rating to the running total
}
$image_rating = round($rating_runningtotal / $numberOfRatings); //this will find the average of all the ratings and round to the nearest whole number
echo $image_rating;



gallery.php - all code
If you love to copy and paste then here is the code for the gallery page:

<html>
<head>
<title>My First Rating System</title>
</head>
<body>
<?php
//DATABASE CONNECTION GOES HERE

$imageQuery = mysql_query("SELECT * FROM images"); //here we query the database for all the images
while($getImages = mysql_fetch_array($imageQuery)){ //now we loop through each of the rows returned from the query above and for each, we do the following code
$imageID = $getImages["imageID"]; //get the image ID from the database
$imageURL = $getImages["imageURL"]; //get the image URL from the database

$rating_runningtotal = 0;
$ratingsQuery = mysql_query("SELECT * FROM ratings WHERE imageID='$imageID'"); //query the database for all ratings which are related to this image.
$numberOfRatings = mysql_num_rows($ratingsQuery); //get the number of ratings this image has
while($getRatings = mysql_fetch_array($ratingsQuery)){ //loop through each rating
$rating = $getRatings["rating"]; //get the actual rating and assign it to a variable
$rating_runningtotal = $rating_runningtotal + $rating; //add the rating to the running total
}
$image_rating = round($rating_runningtotal / $numberOfRatings); //this will find the average of all the ratings and round to the nearest whole number
echo $image_rating;
//
//After this I break out of the php code so I will explain what is happening below, here.
//<img src="<?=$imageURL?>" /> Here we print the images URL from php inside the image src statement to display the image
//<form id="ratethis-<?=$imageID?>" This is simply to give each form a unique identifier, if the imagesID is 1 this will appear as "ratethis-1"
//action="rate.php?id=<?=$imageID?>" This will send the ID of the image to our php function
//
?>
<img src="<?=$imageURL?>" /><br />
<form id="ratethis-<?=$imageID?>" action="rate.php?id=<?=$imageID?>" method="post" >
<label for="Rating">Rate this image: </label>
<select name="rating">
<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>
<input type="submit" value="Rate this!" />
</form>
<?php
}
?>
</body>
</html>


Creating the actual rating php function
So now we have our gallery page where users can click to rate, we now have to make sure that rating goes somewhere! We will create a function which gets the number the user inputs, gets their IP address, checks if the user has already rated and input the rating to the database if they have not rated previously; this will stop people rating more than once.

rate.php

<?php
$imageID = $_REQUEST["id"]; //get the images ID from the url (e.g rate.php?id=1)
$rating = $_POST["rating"]; //get the rating which was posted from the form
$ip = $_SERVER['REMOTE_ADDR]; //get the ip of the user
$checkIPQuery = mysql_query("SELECT * FROM ratings WHERE imageID = '$imageID' and ip = '$ip'"); //select all the ratings where the image id is the same as this one and the same IP is used
$doesIPExist = mysql_num_rows($checkIPQuery); //check how many results match the query above
if($doesIPExist == 0){ //if no results exist
mysql_query("INSERT INTO ratings (imageID, rating, ip) VALUES ($imageID, $rating, $ip)"); //save the rating to the database
echo 'Thanks for the rating!'; //and say thanks!
}else{ //if the ip and image are already present in the database
echo 'You have already rated this image!'; //tell the user they cannot rate this image again!
}
?>


There is your simple, functioning image rating system! I will now show you a few extra tips!

Extra Tips
Tip 1 - Always protect your code from SQL injection whenever you are working with a database, I plan on discussing this in a tutorial in the near future.
Tip 2 - If you wish to add little stars or something for the rating image, this is simple, we create a loop which will go through and place an equal number of images to the rating of the image. Here is the code to do that: (I am assuming your rating image is in a directory at the root called images and the image is called 'star.gif')

<?php
for($i=1;$i<=$image_rating; $i++){ //increment $i while it is less than or equal to the image rating
echo '<img src="../images/star.gif" />'; //print your rating image
}
?>


I hope this helps, any questions or comments - simply use the form below and I will aim to have an answer for you within 24 hours.



Submit Comment

Comments

  1. kollp on November 08, 2014
    guys I Found this tutorial on tch-courses .Watch the Online Video Course PHP with MySQL Essential Training
    http://tch-courses.blogspot.co.uk/2014/11/free-lynda-php-with-mysql-essential.html

  2. fucking on November 28, 2013
    save the life enjoy the real racking phpbworld inside your penis

  3. kapil on July 07, 2012
    achiiii coading hai bt bhut bdi h

  4. prashant on July 07, 2012
    ahh its gud

  5. Matt on December 13, 2011
    Ahh sorry Michael - old site too :( Not even touching PHP much anymore as I'm pretty much fully objective-c

    Sorry for your loss!

  6. re: below on December 13, 2011
    The site "ate" half of my comment. Maaaan, I wrote a bunch of details on another way to go about it completely.

    Oh well, I'm not writing all of that again...sorry

    Michael

  7. MIchael (AKA..tip 3) on December 13, 2011
    Wow, lol - I didn't realize this was written 3 years ago. I saw comments from November of this year and I didn't really read any further. Good job on writing a tut that still has activity 3 years later. Also, good job on continuing to be active on this tut.

    I have a rank idea for you (it's the one I am almost done building).

    specs:

    1) Only logged in users can even see the rank options.
    2) instead of creating a new row for every time a rank is submitted based on user_id

  8. Matt on December 13, 2011
    Thanks for your comments :) This tutorial was written almost 3 years ago and yes it could definitely do with a rewrite :)

  9. Tip 3 on December 13, 2011
    Don't do it this way. There are a lot of mistakes and nooby practices

    1 - "SELECT * FROM ratings WHERE imageID='$imageID'"

    This is traversing every database column (*). It should be:

    1. "SELECT ip FROM ratings WHERE imageID='$imageID'"

    -----

    2. No steps were taken to fail-safe against the database not making a connection.

    should be

    $sql ="SELECT ip FROM ratings WHERE imageID='$imageID'";

    if(!result = mysql_query($sql))
    {
    mysql_close();
    location("header:error.php?er=conn");
    exit;
    }
    else
    {
    $row = mysql_fetch_assoc($result);
    if ($_SERVER['REMOTE_ADDR'] != $row['ip'])
    {
    $sql = "INSERT INTO ratings (imageID, rating, ip) VALUES ('$imageID', '$rating', '$ip')";

    if(!$result = mysql_query($sql))
    {
    mysql_close();
    location("header:error.php?er=conn");
    exit;
    }
    else
    {
    mysql_close();
    location("header:success.php");
    exit;
    }
    }
    else
    {
    location("header:error.php?er=vot)
    exit;
    }
    }

    see what I'm saying? And then in error.php you could just setup a switch/case to handle your errors

    $errors = $_GET['er']'

    switch ($errors)
    {
    case 'conn':
    echo "unable to make a connection";
    break;
    case 'vote':
    echo "you have already voted";
    break;
    default:
    echo "there has been some undocumented error";
    break;
    }

    of course all of this could be expanded on, but the original tutorial for this site leaves a lot of info out. Good try though Matt.

  10. shraddha on November 28, 2011
    good

  11. Tanmay on September 12, 2011
    Its Great!!!!!!!!!!

    It is relay helpful for all little webmasters.....

    Thank you so much.

  12. hasan on August 23, 2011
    thank u sooo much dear...

  13. Rohan kadam on August 04, 2011
    Thanks dud

  14. marry on July 22, 2011
    thanks..It is very helpful..

  15. Matt on July 21, 2011
    Thanks Amanda, glad you found the tutorial useful :)

  16. Amanda on July 21, 2011
    Thanks so much for script really appreciate you posting it. I did have some minor issues with it but it helped me create my own script. As for the comment Michael made I find that was extremely rude. I think if he feels the need to post remarks like that after you took the time and energy to make and post the tutorial I feel he should attempt to make one better and then post the link.

  17. Matt on March 01, 2011
    A little bit harsh Michael but okay. Find out what is happening on line 23 and see what is supposed to be returned as the second part of the division, then work out why it isn't there.

  18. Michael on March 01, 2011
    Your script is garbage and does not run! Here is the error is you wish to correct!
    Warning: Division by zero in C:\xampp\htdocs\gallery.php on line 23
    0

    Rate this image: 1 2 3 4 5

  19. dfdfdf on November 05, 2010
    dfdfd

  20. Niklas on September 10, 2010
    hello, sorry for my english i´m from sweden...
    I like your script wery mutch, and i have try to install it...

    in gallery i have:

    <?php
    $host = 'xxxxx';
    $user = 'xxxxxx';
    $pass = 'xxxxxxx';
    $database = 'vote';

    $dbh = mysql_connect($host, $user, $pass) or die ('I cannot connect to the database because: ' . mysql_error());
    mysql_select_db($database) or die(mysql_error());

    $imageQuery = mysql_query("SELECT * FROM images"); //here we query the database for all the images
    while($getImages = mysql_fetch_array($imageQuery)){ //now we loop through each of the rows returned from the query above and for each, we do the following code
    $imageID = $getImages["imageID"]; //get the image ID from the database
    $imageURL = $getImages["imageURL"]; //get the image URL from the database

    $rating_runningtotal = 0;
    $ratingsQuery = mysql_query("SELECT * FROM ratings WHERE imageID='$imageID'"); //query the database for all ratings which are related to this image.
    $numberOfRatings = mysql_num_rows($ratingsQuery); //get the number of ratings this image has
    while($getRatings = mysql_fetch_array($ratingsQuery)){ //loop through each rating
    $rating = $getRatings["rating"]; //get the actual rating and assign it to a variable
    $rating_runningtotal = $rating_runningtotal $rating; //add the rating to the running total
    }
    $image_rating = round($rating_runningtotal / $numberOfRatings); //this will find the average of all the ratings and round to the nearest whole number
    echo $image_rating;
    ?>
    <img src="<?=$imageURL?>" /><br />

    <form id="ratethis-<?=$imageID?>" action="rate.php?id=<?=$imageID?>" method="post" >
    <label for="Rating">Rate this image: </label>
    <select name="rating">
    <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>
    <input type="submit" value="Rate this!" />
    </form>
    <?php
    }
    ?>

    then in rate.php:

    <?php
    $host = 'xxxxxxxx';
    $user = 'xxxxxxx';
    $pass = 'xxxxxxxxx';
    $database = 'vote';

    $dbh = mysql_connect($host, $user, $pass) or die ('I cannot connect to the database because: ' . mysql_error());
    mysql_select_db($database) or die(mysql_error());

    $imageID = $_REQUEST["id"]; //get the images ID from the url (e.g rate.php?id=1)
    $rating = $_POST["rating"]; //get the rating which was posted from the form
    $ip = $_SERVER['REMOTE_ADDR']; //get the ip of the user
    $checkIPQuery = mysql_query("SELECT * FROM ratings WHERE imageID = '$imageID' and ip = '$ip'"); //select all the ratings where the image id is the same as this one and the same
    $doesIPExist = mysql_num_rows($checkIPQuery); //check how many results match the query
    if($doesIPExist == 0){ //if no results exist
    mysql_query("INSERT INTO ratings (imageID, rating, ip) VALUES ($imageID, $rating, $ip)");

    //save the rating to the database
    echo 'Thanks for the rating!'; //and say thanks!
    }else{ //if the ip and image are already present in the database
    echo 'You have already rated this image!'; //tell the user they cannot rate this image
    }
    ?>^

    when i press to rate it say:
    Thanks for the rating!

    but it dosent insert in to the Table....

    does i have something wrong...

    please help me

  21. Matt on May 02, 2010
    Yeah, it's quite simple with a little jQuery/ajax - When I get around to posting some more tutorials I will put one up :)

  22. fan on March 15, 2010
    anyway to register the rating without leaving the page?

  23. Matt on February 21, 2010
    Sorry not sure what you mean by assign this to smart? Please be more specific and I'll try to help you out :)

  24. Xsell on February 20, 2010
    how do u assign this to smart ..

    <?php
    for($i=1;$i<=$image_rating; $i ){ //increment $i while it is less than or equal to the image rating
    echo '<img src="../images/star.gif" />'; //print your rating image
    }
    ?>

  25. Xsell on February 19, 2010
    Thank you , is not enoght .. but Thank yuo Very Much

  26. Xsell on February 19, 2010
    Thank you , is not enoght .. but Thank yuo Very Much

  27. pido on February 07, 2010
    Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\up\rate.php on line 13
    Thanks for the rating!

    i figured out the error inthe rate.php but i got a new one..

    and here is my code

    <?php

    $con = mysql_connect("localhost","pido","123456");
    if (!$con)
    {
    die('Could not connect: ' . mysql_error());
    }

    $imageID = $_REQUEST["id"]; //get the images ID from the url (e.g rate.php?id=1)
    $rating = $_POST["rating"]; //get the rating which was posted from the form
    $ip = $_SERVER['REMOTE_ADDR']; //get the ip of the user
    $checkIPQuery = mysql_query("SELECT * FROM ratings WHERE imageID = '$imageID' and ip =

    '$ip'"); //select all the ratings where the image id is the same as this one and the same

    IP is used
    $doesIPExist = mysql_num_rows($checkIPQuery); //check how many results match the query

    above
    if($doesIPExist == 0){ //if no results exist
    mysql_query("INSERT INTO ratings (imageID, rating, ip) VALUES ($imageID, $rating, $ip)");

    //save the rating to the database
    echo 'Thanks for the rating!'; //and say thanks!
    }else{ //if the ip and image are already present in the database
    echo 'You have already rated this image!'; //tell the user they cannot rate this image

    again!
    }
    ?>

    hope you answer it ASAP.. needed badly thx..

  28. pido on February 07, 2010
    mr. I got an error and cant do it :(

    Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\up\gallery.php on line 14

    thats in the gallery.php

    and in rate.php

    Parse error: syntax error, unexpected T_VARIABLE, expecting ']' in C:\xampp\htdocs\up\rate.php on line 5

    cant find solutions :(

  29. nadine on January 20, 2010
    You rock! Thank you so much for this tutorial.It helped me build my own script so easily..
    Kisses from Greece!

  30. Matt on January 06, 2010
    Sure, what is the error you are getting Kat?

  31. kat on January 06, 2010
    hey, im having some error and i do not know how to solve it. Can help...
    It shows error on both
    $image_rating = round($rating_runningtotal / $numberOfRatings); //this will find the average of all the ratings and round to the nearest whole number
    echo $image_rating;

  32. Matt on December 02, 2009
    I could be wrong but I was under the impression that <?=$var?> was different to opening a whole block with <?, <?=$var?> is pretty much an echo statement for the variable opposed to a block of PHP.

    Please correct me if I'm wrong :)

  33. CaptJosh on December 02, 2009
    I noticed that some of your php used just <? and some <?php. PHP 5 won't work with just <? for an opening. It has to be <?php.

  34. Matt on October 07, 2009
    What do you mean by both tables in one table Rajesh?

  35. Rajesh on October 07, 2009
    y cant we use both table in one table.? is there is any source..
    im trying for tat..

  36. ramesh on October 02, 2009
    super