June 4th, 2007 - by cpradio

After reading Paul’s article “CSS The Star Matrix Pre-loaded“, I wanted to contribute by writing a back-end solution to the CSS effect.

Before we get into this, you will need to have PHP 5 installed and MySQL 3.23 or higher. PHP 5 allows for greater implementation of OOP (Object Oriented Programming) than its predecessors.

Step 1: Analyze the Project
The first step is always the most crucial, so it should take some thought: What do we want to achieve, and how detailed do we want to get? All of these are questions that should be asked prior to any coding or any development work.

What do we want to achieve and how detailed should we get?
In this project, we want to use Paul’s CSS technique to build a fully functional rating system. Ideally, one that does not require any administration. Everything is automated by pasting a segment of code written in PHP onto a page.

Secondly, we want to ensure that only one IP Address can rate each unique item. Therefore one person isn’t repeatedly clicking on ’5 Stars’ to throw off the rating average. Now granted, ensuring a single IP Address is used in rating isn’t fool proof. As those with dial-up connections will likely have a different IP address every time they reconnect, we have to remember our first goal, “does not require any administration!” No administration means no username and passwords to be assigned.

What about cookies? Glad you asked; I did think of using cookies to do the tracking, but I figured that would be much easier to overcome than basing it on IP address. It has become easier to clear the privately stored data in our modern browsers and thus cookies could easily be foiled.

Our third goal is to adequately show the new average rating when clicked without reloading the entire page. To do this requires the use of AJAX (Asynchronous JavaScript and XML). In our situation, we will be using more of AJANVP (Asynchronous JavaScript and Name/Value Pairs). XML can become very bloated and in something like this it’s simply unnecessary. I also considered JSON (JavaScript Object Notation), but again, that has too many dependencies and further complicates the system requirements for this task. Remember, we are going for no administration and fully automated.

Finally, we want each user to be able to add new ratings without having to insert anything into a database table. Simply put, the HTML components built should derive the rating data for us. I’ll clear this up later, but you should be excited to know that when we are done you will only need to copy and paste code and the new rating entry will be ready for use. Nothing more is required.

Step 1 Recap:
In step 1, we answered the questions “What do I want to achieve and how detailed do I want to get?” The answer can be summarized in these points.

  1. Use Paul’s CSS Star Matrix technique.
  2. Log the Ratings by IP address to ensure no IP address can rate the same item twice.
  3. Update the Rating seamlessly for the user to see the new average rating.
  4. Make it easy to add new items to rate.

Step 2: Designing the Database and Table
Step 2 is designing the storage facility to keep our information. There are a few questions to ask yourself when designing a table like this. What information do you plan to hold in it? How do you plan on using the data?

What information do I plan to hold in the table?

Below is the list of the data we plan to keep track of:

  • Item Name
  • IP Address
  • Rating
  • Date Rated

There won’t be much use immediately for Date Rated, however, it could be used in the future to build any reports on when each item was rated.

How do you plan on using the data?

Each item you plan to keep track of should ALWAYS have a use, whether it be immediate or in the future. For example, Item Name, IP address, and Rating will all be used immediately within this application. The Item Name will describe the item being rated, the IP address is the IP address of the person rating the item, and Rating, is course their rating for the specific item.

Date Rated is there for a future use. It has no immediate use, primarily because it is outside the scope of this project, but as I mentioned before, it could be used to generate reports in the future.

Step 2 Recap:

Here we defined what we will be tracking, how it will be used, and whether it has immediate or future use. Item Name, IP address, and Rating all have immediate use — only Date Rated is considered future use.

Step 3: Building the Database and Table
You can opt to create a new Database or use an existing Database; the option is yours and will have no impact on this application. For those wanting to create a new Database, you can use the following MySQL query (replacing the word ‘ratings’ with your database name):

CREATE DATABASE 'ratings' DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Nothing special about the Database creation, as all of the little details are found in the table. The table will hold all of the information we described in Step 2 above.


CREATE TABLE `rating` (
`item_name` VARCHAR( 20 ) NOT NULL ,
`ip_address` VARCHAR( 15 ) NOT NULL ,
`rating` TINYINT( 1 ) NOT NULL ,
`date_rated` DATE NOT NULL ,
PRIMARY KEY ( `item_name` , `ip_address` )
) ENGINE = MYISAM ;

Notice that the primary keys are “item_name” and “ip_address”. This is to help ensure that no “ip_address” can be used to rate the same “item_name”. Also notice the lengths of each item. Item Names are not allowed to be more than 20 characters. If you want to have Item Names that are longer than 20 characters, you will need to alter the above statement with the length you want to use (up to 255).

Step 3 Recap:
We defined our Database and table so the rating information can be stored. We set the “item_name” and the “ip_address” columns as our Primary Keys to ensure only one IP address can rate each Item Name. We also defined the max name length for Item Name as 20.

Step 4: Writing our Rating Class
Strong OOP skills are something to never overlook, as they provide you with clever ways of extending your work in the future, plus they focus entirely on being reusable. With that said, you may remember my previous articles “OOP in PHP from a .NET OOP Perspective: The Error Class” and “OOP in PHP from a .NET OOP Perspective: The Database Class.” These two articles are going to be used in this project as well. The Error Class will handle any Database errors we might have, and the Database class will handle the Database connection, Query Execution, etc.

To go any further, you will need to download the following file: RatingSystem.zip

After it has downloaded, extract the contents to your computer. You should see a ‘RatingSystem’ folder. This folder is our example application, go ahead and browse to the RatingSystem > classes folder.

Open the rating.class.php file in any editor. This is the class that will be used to output the rating information to the page and record a rating by a user.

Now I won’t get into all of the code here (you’ll have to read those other articles), but I will point out a few things.

  1. The first thing you should notice is the OutputRating method. This method is what loads the CSS technique written by Paul. If you look at lines 31 and 44, you will see his technique used. I also made a few modifications to it (of which I hope he does not mind, but I will describe those later).
  2. Next find the RateItem method (approximately line number 66). This method writes the user’s rating to the table. So if you changed the table name, you will want to update the table name in this method as well.
  3. On line number 111 is the CalculateAverageRating, this method calculates the average rating of an item within the MySQL statement. Again, if you choose a different table name than described in this article, you will want to update this statement to reflect that change.
  4. Finally, I want to point out line number 170, the CheckRatingsByIp method. This is the last place you may have to update the table name if you did not use ‘rating’.

Step 4 Recap:
I provided you with the files to run this rating system and gave key pointers on where the table names may need updated if you opted to use a different name.

Step 5: Setting the Database Connection

To set the database connection open the “include.all.php” file in the “classes” folder. Notice the line:

  1. Database::Initialize("mysql", "localhost", "3306", "ratings", "username", "password");

Replace “ratings” with your database name, username with your database username, and password with your database password.

Once finished, save the file.

Step 6: How to output the Rating information to your page
To display the rating information on your page, you will need to do four things.

  1. Place the following snippet at the top of your file (for an example, look at ‘rating-example.php’ in the RatingSystem folder).

    1. require_once("classes/include.all.php");
  2. Next you need to have the following in your <head> tags:

    <link type="text/css" href="styles/rating.css" rel="stylesheet" media="all" />
    <script type="text/javascript" src="scripts/prototype.js"></script>
    <script type="text/javascript" src="scripts/rating.js"></script>

    This code is what sets the stylesheets, AJAX calls, etc. within your page.

  3. Next, find the location you want to output your Rating Stars and paste this code:
    1. $ratingData = Rating::OutputRating('demo');
    2.  
    3.   if (Error::HasErrors())
    4.   {
    5.     echo Error::ShowErrorMessages();
    6.     Error::ClearErrors();
    7.   }
    8.   else
    9.   {
    10.     echo $ratingData;
    11.   }
  4. Finally, end the page with the following code:
    1. Database::DeInitialize();

Replace the word ‘demo’ with the name of your Item. If no errors occur, you should see the 5 stars not lit up when you run the page, otherwise, you will see the error messages that occurred.

Step 5 and 6 Recap:
In Step 5 and 6 we entered the Database connection information, and we pasted our code to show the Rating System for a specific item.

That’s it! There isn’t anything else needed to get this working. All you have to do is copy the same snippet of code wherever you want it to appear on your page. You can have one item to rate on a page, or you can have 10. Just give them all unique IDs and they can all be on the same page.

Even though you now have a working Rating System, allow me to give you one last walk through of this system.

Crash Course Walk-Through
This walk-through will be based on the “rating-example.php” file from the top-down, not necessarily in processing order.

When your page is loaded, the “classes/include.all.php” file is loaded which establishes your Database connection, initializes the Error class, and allows the Rating class to be used.

Following this, the StyleSheets and JavaScript files are loaded to ensure the Rating System outputs properly and the AJAX capability is setup.

Next the Rating::OutputRating is called to show the rating details of ‘demo’. If an error occurred our error messages are shown, otherwise, it will display the stars lighting up the current rating.

Once the processing is finished, the user will see the page generated.
Rating System Page

When the user hovers over a rating that they have not rated before, the stars light up appropriately.

Rating System Page Hover

Finally, when the user clicks a star, it is recorded and the average rating is shown to the user with green stars. Note that even if the user hovers over the stars, they will not light up because they have already cast their vote and rated that item.

Rating System Page Rated

Now this is where I altered Paul’s code. I created a new class called ‘rated’ (found in the “styles/rating.css”) that does not contain the hover effect. This way if the user already rated an item, they do not the see the hover effect for the item they rated.

When the user clicks on a star, an AJAX event is sent, the rating is calculated, and then the information is returned in a Name/Value pair. For example, it might return: “item=demo&classes=rated threestar”. Simply put, it means the user clicked on the ‘demo’ item, and the new classes to use on that item are ‘rated’ and ‘threestar’. The class “rated” defines the user has rated that item, and no longer provides the hover effect, and the class “threestar” is the average rating for the item, so it is to light up three green stars.

Conclusion:
That ends the task of providing a functional Rating System using Paul’s CSS Star Matrix Pre-Loaded technique. I want to thank Paul for the excellent CSS work, and hopefully I have done it a bit more justice by adding the back-end functionality.

Feel free to leave any comments, remarks, questions, etc. as I will be happy to answer them.

39 Responses to “CSS The Star Matrix Pre-loaded: Part 2”

1 CSS The Star Matrix Pre-loaded

[...] sure to check out part 2 of this article for the back-end solution! Book it: del.icio.us, digg, Reddit, YahooMyWeb Subscribe to this feed! Subscribe to [...]

2 Paul OB

Excellent explanation and implementation. I think even I could have a go at setting that up :)

3 cpradio

Thanks Paul, I tried keeping it simple enough for the new user to handle, yet extendable for the more experienced.

I feel I accomplished that. :)

4 Golgotha

Great write up Matt, I will try it out this weekend…

5 DotNetNuke

I have read first part, however couldn’t find enough time to try that, hopefully i will try this at next weekend.

6 ses5909

Nice post Matt. I definitely see a place to use this!

7 Jelena

Those two posts together are one great tutorial and practical solution which can be used an implemented very eaisly.

Thanks to both of you.

8 Ishaq Chughtai

Excelent Explaination. Thanks Paul.

9 Ishaq Chughtai

Its very good sample. You can use everywhere in your php page simply.

10 Mack

This script works fine for me in firefox 2.0, but refuses to show up in IE6 or 7. I did change the star size, but I can’t figure out where I am going wrong in IE.

Awesome Script btw. Digg worthy.

.rating{
width:125px;
height:25px;
margin:0 0 20px 0;
padding:0;
list-style:none;
clear:both;
position:relative;
background: url(../images/star-matrix.gif) no-repeat 0 0;
}
ul.rating li {
cursor: pointer;
/*ie5 mac doesn’t like it if the list is floated\*/
float:left;
/* end hide*/
text-indent:-999em;
}
ul.rating li a {
position:absolute;
left:0;
top:0;
width:25px;
height:25px;
text-decoration:none;
z-index: 200;
}
ul.rating li.one a {left:0}
ul.rating li.two a {left:25px;}
ul.rating li.three a {left:50px;}
ul.rating li.four a {left:75px;}
ul.rating li.five a {left:100px;}
ul.rating li a:hover {
z-index:2;
width:125px;
height:25px;
overflow:hidden;
left:0;
background: url(../images/star-matrix.gif) no-repeat 0 0
}
ul.rating li.one a:hover {background-position:0 -150px;}
ul.rating li.two a:hover {background-position:0 -175px;}
ul.rating li.three a:hover {background-position:0 -200px}
ul.rating li.four a:hover {background-position:0 -225px}
ul.rating li.five a:hover {background-position:0 -250px}

/* this is used to remove the hover affect */
/* use the background position according to the table above to display the required images*/
.rated{
width:125px;
height:25px;
margin:0 0 20px 0;
padding:0;
list-style:none;
clear:both;
position:relative;
background: url(../images/star-matrix.gif) no-repeat 0 0;
}
ul.rated li {
cursor: pointer;
/*ie5 mac doesn’t like it if the list is floated\*/
float:left;
/* end hide*/
text-indent:-999em;
}
ul.rated li.one a {left:0px;}
ul.rated li.two a {left:25px;}
ul.rated li.three a {left:50px;}
ul.rated li.four a {left:75px;}
ul.rated li.five a {left:100px;}

/* add these classes to the ul to effect the change to the correct number of stars */
.nostar {background-position:0 0}
.onestar {background-position:0 -25px}
.twostar {background-position:0 -50px}
.threestar {background-position:0 -75px}
.fourstar {background-position:0 -100px}
.fivestar {background-position:0 -125px}
/* end rating code */
h3{margin:0 0 2px 0;font-size:110%}

11 Nishi

Good, clear, and a well explained tutorial. Keep it up!
Have you also looked into partial stars rating i.e. something like 3.5/5.0.

12 cpradio

Nishi,

To do this, all you would need to do is add those extra stars into the images, update the CSS classes to have the half values as well, and then update the PHP script to return onehalfstar, twohalfstar, etc. for class names.

13 Nishi

Thanks for your suggestion. I’ll be working on it.

Just curious, is there a way to display any rating, not just one or half stars? In the environment I work in, users want to see the exact rating, not the one rounded up/down to a one/half star.

14 cpradio

You would have to create a background image that supports all of those potential ratings. Probably down to the 10th.

In either case, you will have to show an approximate with the stars, the alternative you can return text in the Ajax for the ToolTip to state the exact number while still showing the approximate number in the image.

Matt

15 Markus

I’m looking for a solution that shows me the top3 rated entries in my database.
But I don’t know how to write that as an SQL statement..
Does anyone has an idea?

16 cpradio

Markus, run the following:
SELECT `item_name`, SUM(`rating`) AS `totalRating` FROM `rating` GROUP BY `item_name` ORDER BY `totalRating` DESC LIMIT 0, 3

17 Markus

great, works fine, thanks!

18 cpradio

Just an FYI, you can change the LIMIT 0, 3 or remove it to get more results than the top 3. For example, LIMIT 0,5 will return the top 5 or just removing it will return all of the totals for every item.

Matt

19 cpradio

My apologies Markus, I accidentally gave you a slightly incorrect query. The query I gave you only returns the ratings with the greatest sum of votes. Not the highest averages.

Here is one for the highest averages:
SELECT `item_name`, AVG(`rating`) AS `totalRating`
FROM `rating`
GROUP BY `item_name`
ORDER BY `totalRating` DESC
LIMIT 0, 3

20 Markus

as I have to get data from two tables this is my statement now:
SELECT
u.uid,
u.name,
u.” . STATEMENT . “,
AVG( r.rating ) AS \”averageRating\”,
r.item_name
FROM
fe_users u
LEFT JOIN
user_rating r ON u.uid = r.ref_uid
WHERE
u.deleted = 0
AND
u.disable = 0
AND
u.usergroup LIKE ‘%3%’
AND
u.” . STATEMENT . ” ”
AND
r.item_name \”\”
AND
r.item_name LIKE ‘%$strCategory’
GROUP BY
r.item_name
ORDER BY
\”averageRating\”
DESC
LIMIT 3″;

the SUM thing I’m requesting in a second statement

21 cpradio

That works :)

22 CosmoSwiller

Hello there.

I’m trying to develop a star rating system to be used on an intranet. As you can imagine this causes some problems with using an IP address to identify different users. Does anyone know of a tutorial for a star rating system that uses cookies to identify unique users. Or failing that, a system that has no checks in place. As l’d just like to get the thing working not that bothered about the actual results.

Thanks in advance, and thanks to all the people who give up their time to create things such as this tutorial.

Cosmo

23 fork

Heads up. I installed this script as is. It had some blow up regarding rating.class.php to my consternation. A php notice for missing variable $classes for all the ratings and an unstyled list when the star was clicked on.

I simply changed line 146 that reads: case 1:
$classes .= “onestar”;
break;

to

case 1:
$classes = “onestar”;
break;

removing the concatenation dot from before the equals sign in all the cases. Now works like magic. Long post but trying to save some headache for my designer who delves into server side code brethren.

24 Joel

Hi Cpradio Are we supose to write some coding around lins 31 and 44 exactly where paul css rating technique is?

if yes tell me please i have already build paul’s tecnique sucessfully and personalized with orange squares with some of his help, please give me a hand on the database part…

25 Joel

Another query is that you wrote the class Rating with capital letters and worte it with lowercase letter does it make a difference?

26 Joel

I know I am going to fast but just answer the question at your pace, I have another query in step five you said to observe this line
1.Database::Initialize(“mysql”, “localhost”, “3306″, “ratings”, “username”, “password”);

And then replace it with my database respective name, username, password.

I don’t know where is my database and how can I create one, what is it for and where can I find the name, username and password to replace if the database is created already.

Thank you in advance and excuseme for asking so many question behind the other both of your work your and paul’s are awsome.

27 Joel

Cpradio How much i would want you to appear here,

I am getting this errors and I been having a pretty hard time figuring it out:

Warning: require_once(error.class.php) [function.require-once]: failed to open stream: No such file or directory in C:\wamp\www\include.all.php on line 2

Fatal error: require_once() [function.require]: Failed opening required ‘error.class.php’ (include_path=’.;C:\php5\pear’) in C:\wamp\www\include.all.php on line 2

28 Marc Morgan

Hello,

I am trying to implement this rating system. I have changed it to 10 stars and the rollover is working correctly. When I click the stars it send to the database but the “Rated” phase doesn’t get called… I can’t seem to figure out how to implement this..

Can you please help me. Do you have paypal ?

29 Marc Morgan

Would there be a reason that this would work “out of the box” with “rating-example.php” but not when i try and use it with a different file to address the rating system.????

The on mouse roll over works but when i click, nothing happens…

All of the paths are set correctly.

Any ideas?

Thank you

30 co.ador

something similar is happening to me The “rated” is not showing the nostar row before any user has rated the item… how can pull the format information out the rated css class?

31 Chris

Looks like there isn’t any help here anymore, but I figured I would try. I am using this script and it works wonderfully. The one question I have is how can I add another item into the database. I have a members section to my site and people can only rate when they are logged in. I want to add the username to the database and have it input the name whenever an item is rated so I know who is rating what.

Thank you for this tutorial and any help.

Chris

32 Chris

Also, just a late response to co.ador and Marc Morgan. I was having a similar problem and it was because I didn’t have all of the files uploaded (mainly the ajax.rate.item.php) file.

33 co.ador

Chris where does the ajax.ratre.item.php file goes?

i am having some trouble again with entering the rating to the database it is not going in to the database?

any ideas

joelitos at hotmail.com

34 Sadesh

Hello!

I get this error message, I think it has something to do with me using php 5.x and some functions in this script that are not supported in this version\

Can somebody fill me in why I get the following error message after implementing?

Deprecated: Function split() is deprecated in C:\wamp\www\ThumbsUp\classes\database.class.php on line 397

Notice: Undefined variable: varName in C:\wamp\www\ThumbsUp\classes\rating.class.php on line 132

Notice: Undefined variable: classes in C:\wamp\www\ThumbsUp\classes\rating.class.php on line 161
ERRORS:
Database Selection at 03/11/2010 15:24:04
Unknown database ‘ratings’

Query Failed at 03/11/2010 15:24:04
No database selected

Free Results Error at 03/11/2010 15:24:04
No database selected

Query Failed at 03/11/2010 15:24:04
No database selected

Free Results Error at 03/11/2010 15:24:04
No database selected

35 Nicholas Smith

Hello, your script is a blessing. Would you be willing to tell me how to use it with php 4.3.11 I have yahoo hosting and they will not upgrade for another year. Or will this work either way?

36 Yolandie

Hello everyone! I have no experience with php, ajax, jquerie and only use dreamweaver to write my html, css code and very basic javascript. Part 1 was so easy, but i’m not sure where to go from here as i don’t have and don’t know how to use php5 or MySQL as a prerequisite for part II of this tut to complete the backend.

Can someone please please please help me out over here?

37 Chris

Hey,
So I’m back to offer what little help I can.

co.ador – that file goes in your main web directory. Also if its not going into the database, make sure your database settings are 100% and if you changed the name of the table you changed it in the rating.class.php file where directed to by this tutorial.

Sadesh – The split problem is easy, just go to php.net and search for split and it tells you the tag you should now use instead. (I believe preg_split is what should be used now). The other errors are because you have must have your database settings wrong. In the include all file you should have this line set to your database settings:
Database::Initialize(“mysql”, “localhost”, “3306″, “DATABASE NAME”, “USERNAME”, “PASSWORD”);
If your mysql settings are default then you shouldn’t have to change the first three items just the last three. Also like I said to co.ador, if you changed the table name from ratings make sure you adjust it as necessary.

Nicholas Smith – This script should work fine with php 4.3x. I can’t say for sure, because I do use 5.x but you should be good as long as your database is setup.

Yolandie – Sorry, but its not that easy to just explain what you need to do. You will need some basic knowledge to handle the php and mysql. Try reading a php/mysql tutorial, I suggest webmonkey (http://www.webmonkey.com/2010/02/php_and_mysql_tutorial_-_lesson_1/). That is a more updated tutorial but I started out with a similar tutorial on webmonkey.

38 Sleeper

Hi, I recently came by this tutorial and it’s just what I’ve been lookin for – really nice! I have but one problem though:

I get the following error:
Undefined variable: classes in C:\wamp\www\RatingSystem\classes\rating.class.php on line 158

The stars show up fine, I click the selected range and then the error message shows and I get numbers listed vertically (1 to 5). After a browser refresh the stars reappear with the correct star selection.
The database is being written to successfully.

Any help greatly received.

39 Sleeper

Solved… I read back over the thread – Fork had alrady provided the solution. Removing the concatentation from the Case.
Thanks!

mulberry sale spyder womens jacket cheap new balance 574 mulberry outlet cheap new balance 574 arcteryx outlet mulberry sale spyder womens jacket mulberry sale spyder womens jacket mulberry outlet mulberry outlet new balance 574

Popular Articles

Top 10 Commentators


Subscribe to this feed! Subscribe by Email!

Random Bits Podcast

You need to download the Flash player from Adobe

Blogs Worth Reading


    Warning: fopen(./wp-content/themes/big-blue/my_blogroll.php): failed to open stream: Permission denied in /home/mangeletti/search-this.com/wp-content/themes/big-blue/get_blogroll.php on line 5

    Warning: fread() expects parameter 1 to be resource, boolean given in /home/mangeletti/search-this.com/wp-content/themes/big-blue/get_blogroll.php on line 6

    Warning: fclose() expects parameter 1 to be resource, boolean given in /home/mangeletti/search-this.com/wp-content/themes/big-blue/get_blogroll.php on line 7
  • Smashing Magazine