Community Documentation

Use Node Comment and Fivestar to Create Advanced Reviews

Last updated June 27, 2008. Created by greg.harvey on March 15, 2008.
Edited by add1sun, quicksketch. Log in to edit this page.

Note that at the time this was written, fivestar required nodecomments. Fivestar can now be used on regular comments as well.

What You Will Need

Latest stable versions of:

* Drupal 5.x
* Fivestar
* Voting API
* CCK
* Views
* Node Comments

This tutorial was specifically written using the following environment:

* Windows XP Pro
* XAMPP 1.6.2
* Drupal 5.7
* Fivestar 1.11
* Voting API 1.5
* CCK 1.6
* Views 1.6
* Node Comments 1.0

This should work for Drupal 6.x too in time, but not just yet. Too many of the required modules are still in alpha and beta states.

Node Comments, why you need it

The problem with comments in the Drupal core is they are not nodes. This means you cannot do any of the neat stuff you can do with nodes with comments. Unfortunately this includes (amongst many other things) rating them. But don't worry! Help is at hand in the form of the Node Comments module. It does what it says on the tin - replaces the core Comments module with a mechanism for commenting via normal content types, so your comments become nodes.

As a result we can use them with the Views module, rate them, give them TPL files, etc. etc.

YOU CANNOT CONTINUE WITH THIS TUTORIAL UNLESS YOU HAVE NODE COMMENTS INSTALLED, which means you cannot use the core Comments module and follow this approach to content rating.

One word of caution though. The implication of moving from Comments to Node Comments is some other modules you may require may not work. For example, the core Forum module does not work with Node Comments AFAIK (and at time of writing, obviously). Do your homework before you make the switch, and where Node Comments are not supported by a module, make sure you are happy the alternatives work.

Basic Reviews - One Rating Field per Node Comment

For the purposes of a demonstration, I will use Quicksketch's website for Good Charlotte as an example use case. It is a website for a rock band where you can listen to their album and then rate it with a comment. To achieve this we need:

* a content type which we expect to rate (call it "album")
* a content type for storing our ratings (call it "review")

So, you've installed all the modules listed above and you're all set.

Create content types

Create a new content type called "review" (admin/content/types) for the comments on our content we wish to rate. For now leave everything default and just save it. Then create a new content type called "album", again leaving defaults, but this time before saving your new content type, near the bottom you should see options called "Default comment setting". Make sure this is set to Read/Write. While you're here, the next option should be "Node type for comments" - pick your new "review" content type from the available list and save your "album" content type.

Reviewing what we just did, we should now have two new content types:

* review - Title and Body fields
* album - Title and Body fields and comments enabled with content type set to "review"

Enable Fivestar on the target

Now, edit the "album" content type. Towards the bottom of the edit page there should be a field group of items labeled Fivestar, possibly collapsed by default. (If so, expand it.) Check the "Enable Fivestar" box and under the "Direct ratings widget" field group set "Teaser display" and "Full node display" to Hidden. Then save.

We have now switched on Fivestar for our rateable "album" content type, but hidden the ability to rate directly on the node from our users (because we want to do this via our comments... the "reviews"... right?)

Add a Fivestar CCK field

Edit the "review" content type. Click the "Add field" tab, type in "Rating" as the field name and pick Fivestar Rating -> Stars as the type. Click the Create field button. You will be taken to the configuration page for your newly created Rating field (which will be the CCK field called field_rating).

Most of the options before you are about visual appearance at this point - the key one is "Target Node ID". This is how Fivestar knows which node your rating is intended for. Vital! There is a checkbox labeled "Use Node Comment Parent as Target", which you should check. Alternatively (and this is the approach I took) leave that box UNCHECKED and paste the following code (provided by Quicksketch) in to the "Target Node ID" text box:

<?php
if (arg(0) == 'node' && arg(1) == 'add' && is_numeric(arg(3))) {
  return
arg(3);
}

if (
arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'edit') {
 
$node = node_load(arg(1));
  return
$node->field_rating[0]['target'];
}

if (
arg(0) == 'node' && is_numeric(arg(1)) && arg(2) != 'edit') {
  return
arg(1);
}

drupal_set_message('An error occurred saving your review, no target was specified.', 'error');
return
0;
?>

Save your field settings.

Displaying your Fivestar average score

Ok, so this is all well and good, but we haven't actually outputted our field to screen (remember, we hid the widget on the node, so right now there is no Fivestar widget or rating visible on our "album" nodes). We need to create a template for our new content type.

Browse to the directory where your theme lives (see PHPTemplate documentation for more information on theming if you are not familiar with how it works), copy your node.tpl.php file and name the copy node-album.tpl.php. Open it in your favourite SDK/text editor and add this code where you want the average rating from your "reviews" to appear:

<?php
$current_rating
= votingapi_get_voting_result('node', $node->nid, 'percent', 'vote', 'average');
print
'<div><strong>Rating:</strong>';
print
theme('fivestar_static', $current_rating->value);
print
'</div>';
?>

Save the template file. Note, if you read the documentation for the votingapi_get_voting_result() function there are other available options you may wish to use.

Create some actual content

First Create an Album. Just give it a title and some Body text. When you submit the new Album node then you should be taken to it. There should be an empty Fivestar widget shown on the page, where you placed it in your template file.

There should also be an "Add new review" link, provided by Node Comments, already underneath the Album node view. (Permissions permitting! - no link, check your permissions - does your role have permission to create "review" content?)

Click the link and you should have a Title, Body and Rating (in the form of a Fivestar widget). Fill in the Title and Body for your "review" and rate your content by using the Fivestar CCK Rating widget you set up. Then click Submit.

Don't forget to run cron!

Now you will need to run cron (because of the current Voting API bug - see the top of this howto) in order to see your vote working. You can do this by going to Admin -> Logs -> Status report (admin/logs/status) ... there is a "run cron manually" link there. After running cron, navigate back to your Album and you will see the vote from your comment appears.

IMPORTANT NOTE: if you create a new comment as the same user on the same album, your previous vote will be over-written, not added to. If you wish to test the 'average' function by creating more reviews, you must do so as different users. This behaviour is BY DESIGN. If you don't like it, create a patch and publish it back to the community. =)

Advanced Reviews - Multiple Voting Axis per Node Comment

If you've followed this far, you should have a working average rating on your "album" content type being provided by the comments underneath of type "review". But let's say we want another couple of possible star ratings on our "review" content type, which are still relevant to our "album". Consider the rating from the simple approach to be our "overall rating", but consider we want two additional rating fields, "singing" and "musicianship" (this is a harsh website we're building here!)

Create multiple Fivestar CCK fields with different axes

Edit your "review" content type and re-follow the steps for adding a Fivestar CCK field, this time naming the field "Singing". Before you save the field settings (after pasting the code in the "Target Node ID" box) this time you need to give it a "Voting Axis". Type 'singing' (without the quotes) in the "Voting Axis" field and save your settings.

Do the above again for a field called "Musicianship" with 'musicianship' as a "Voting Axis". Finally, change the label on your original CCK field, "Rating", to "Overall rating" so it makes more sense.

Create a new review

Now go back to your original Album node and "add new review" again. This time you should see all three Fivestar CCK widgets:

* Musicianship
* Overall rating
* Singing

Fill in your review fields (just Title and Body in our case), give votes for your three Fivestar fields and click Submit. Run cron again.

Showing our extra Fivestar fields in the template

We have registered some votes on different axes, but we're currently only actually displaying the "Overall rating" field. To display all three axes on our node, we need to replace the code we initially placed in our template file with this:

<?php
$current_rating
= votingapi_get_voting_result('node', $node->nid, 'percent', 'singing', 'average');
print
'<div><strong>Singing:</strong>';
print
theme('fivestar_static', $current_rating->value);
print
'</div>';

$current_rating = votingapi_get_voting_result('node', $node->nid, 'percent', 'musicianship', 'average');
print
'<div><strong>Musicianship:</strong>';
print
theme('fivestar_static', $current_rating->value);
print
'</div>';

$current_rating = votingapi_get_voting_result('node', $node->nid, 'percent', 'vote', 'average');
print
'<div><strong>Overall:</strong>';
print
theme('fivestar_static', $current_rating->value);
print
'</div>';
?>

Refresh your Album page and you should see all three average votes now. The key thing here is the fourth parameter being passed to the votingapi_get_voting_result() function. It is a string representing the axis you defined when you created your Fivestar field. By default (if you leave "Voting Axis" blank in your CCK config) it will be 'vote' (see Overall rating). To show votes from a different axis, simply call the votingapi_get_voting_result() function with the appropriate axis name as the fourth parameter (called 'tag' by the Voting API).

Advanced: Voting API - what's going on?

If you are interested, a quick look at the Voting API tables, votingapi_vote and votingapi_cache, is worth it. In essence, when you create your "review" and save it, Fivestar creates a vote in the votingapi_vote table for each CCK field. It differentiates between which field is which by putting the "Voting Axis" text in Voting API's 'tag' column.

Whenever cron runs, the Voting API module calculates the average (amongst other functions available) for each node and 'tag' combination and saves a row in the votingapi_cache table. The results can be retrieved from this table by using votingapi_get_voting_result() and telling it which node, function and 'tag' (AKA "Voting Axis") you wish to display.

Compatibility Notice: Issue with VotingAPI

At time of writing, due to a problem with VotingAPI (as far as I can tell) you need to set Voting API settings to "Tally when cron runs" for the voting cache to be set.

Written by Greg Harvey - http://www.drupaler.co.uk

Comments

Without nodecomment

You can actually rate with normal comments in more recent versions of fivestar. If you don't want to do anything with the reviews except show them on the node, that's an easier method. If you can't use nodecomment but want to have your reviews be nodes, I wrote a tutorial last October that may still be of use: http://shellmultimedia.com/tutorials/rate-and-review-2

Michelle

--------------------------------------
See my Drupal articles and tutorials or come check out life in the Coulee Region.

-----
Shell Multimedia - My sporadically updated mostly Drupal blog.

Cron work around/ custom node type

To avoid having to Tally on cron, add this line to your template:

<?php if (variable_get("votingapi_calculation_schedule", "immediate")=="immediate") { votingapi_recalculate_results('node', $node->nid, TRUE); } ?>

To do this without NodeComment and use any arbitrary node type as your review type, create a required Node Reference field (called 'YourReference' below) to select the node to be rated, and set your "Target Node ID" as:

<?php return $_POST['field_YourReference']['nids']; ?>

interested in your do this without nodecomment

Hi matt2000,

i am interested to know more about your method of creating advanced reviews without the use of nodecomment.

specifically, i have troubles displaying the link of the parent of review when viewing the review as a node by itself.

i am very new to drupal and know very little about php.

I have chosen to use the nodecomments way is because i want to have a easy "add new review link" below the body of the product node and same time be able to display a list of reviews below the product and use the fivestar module.

I hope you can advise me on your method so that it may help.

thanks

Drupal 6 - Displaying your fivestar average score

Everything here is working on Drupal 6.x, except I can't figure out how to calculate the average score. The provided code:

<?php
$current_rating
= votingapi_get_voting_result('node', $node->nid, 'percent', 'vote', 'average');
print
'<div><strong>Rating:</strong>';
print
theme('fivestar_static', $current_rating->value);
print
'</div>';
?>

...will not work with voting_api in drupal 6. The function votingapi_get_voting_result is no longer a part of the module.

If anyone has figured out the d6 code, please post.

- Derek Walker

Allow user to clear value - breaks user editing reviews

After tinkering a bit i found that if you leave under Review Settings "Allow user to clear value" when creating a new field the user will not be able to update their ratings correctly when editing their comments.

It also appeared that the system will break down and no longer allow for the user to adjust their ratings when editing too.

If you're having problems take a look at this setting. :)

For D6

<?php
$current_rating
= votingapi_select_results(array('content_id' => $node->nid, 'function' => 'average'));
print
'<div><strong>Rating:</strong>';
print
theme('fivestar_static', $current_rating[0]['value'], '5');  //this is for 5 stars, enter 10 (or whatever) instead as appropriate
print '</div>';
?>

Advanced Web Design

How about D6 with multiple axes?

I can't find in the votingapi_select_results() documentation where the field name can be specified in the array.

me either - did you find it?

me either - did you find it? I can get average but don't know how to get multiple axis averages printing in drupal 6.

Drupaling along...
Balance Bikes Canada

This may not be the most

This may not be the most efficient way but this is how I achieved it in Drupal 6

<?php
  $customer_service
= votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'customer_service', 'function' => 'average'));
 
$reliability = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'reliability', 'function' => 'average'));
 
$features = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'features', 'function' => 'average'));
 
$price = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'price', 'function' => 'average'));
 
$current_rating = ($customer_service[0]['value'] + $reliability[0]['value'] + $features[0]['value'] + $price[0]['value']) / 4;
  print
'<div class="fivestar-rating">'. theme('fivestar_static', $current_rating, '5') .'</div>';
?>

- Vivian

- Vivian

Hi, could anyone point out

Hi, could anyone point out where I'm going wrong! You'll probably notice in a second that I'm useless at PHP as I've hacked together this code using the example above:

<?php
  $design
= votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'design', 'function' => 'average'));
 
$performance = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'performance', 'function' => 'average'));
 
$value = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'value', 'function' => 'average'));
 
$current_rating = ($design[0]['value'] + $performance[0]['value'] + $value[0]['value']) / 3;
  print
'<div class="fivestar-rating">'. theme('fivestar_static', $current_rating, '10') .'</div>';
?>

Design
<?php
  $design
= votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'design', 'function' => 'average'));
 
$design_current_rating = ($design[0]['value']);
  print
'<div class="fivestar-rating">'. theme('fivestar_static', $design_current_rating, '10') .'</div>';
?>

Performance
<?php
  $performance
= votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'performance', 'function' => 'average'));
 
$performance_current_rating = ($performance[0]['value']);
  print
'<div class="fivestar-rating">'. theme('fivestar_static', $performance_current_rating, '10') .'</div>';
?>

Value
<?php
  $value
= votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'value', 'function' => 'average'));
 
$value_current_rating = ($value[0]['value']);
  print
'<div class="fivestar-rating">'. theme('fivestar_static', $value_current_rating, '10') .'</div>';
?>

For testing purposes I have rated the "design", "performance" and "value" axis as 10 stars each, However, when printing out the average for each axis as well as the overall axis I'm a bit lost. The ratings are only displaying the rating of the the last submitted review and not the average of all reviews.

Can anyone point out what might be wrong?

P.s. I'm using the node relativity module, so the ratings are taken from a related node, but on the related node the ratings are displayed correctly, it's only on the parent node where I'm having problems displaying the average ratings.

Thanks to anyone that can help.

My new EasySnoozing, Nursing and BusinessEgghead websites on D7!

I cannot get the D6 code to

I cannot get the D6 code to work either. I am trying to do multiple axis ratings of "Node A" which is being referenced by "Node B". "Node B" is the node in which the fivestar field rating is being performed. When I visit "Node A", I just see a blank widget (I have submitted a few "Node B's" so the average should be displayed). Here is the code I used:

<?php
  $high_rating
= votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'high', 'function' => 'average'));
  print
'<div><strong>Average High Rating:</strong>';
  print
theme('fivestar_static', $high_rating[0]['value'], '5');
  print
'</div>';
?>

"high" is the axis I used for the "High Rating".

David

What about multiple axis on the default comment module?

Is there a way to put multiple voting axis on the default comment module. That would seem to be ideal.

http://www.louisvillewebgroup.com/ - We Help You Sell Stuff Online

Download Ecommify, a Free Drupal Commerce theme/distribution. http://www.louisvillewebgroup.com/project/ecommify

It'd be great to have multiple axis for a comment or a node, so that the users wouldn't need to comment/create a node just to leave a multiple rating.

Thanks.

What about voting api filter?

First,thank you for so excellent solution for nodecomment with fivestar!

It works very well in my site,except when I try to add views filter 'voting api percent vote value'.
I can make list of title of nodecomment(in above example,'review') with username who added it with views.But when I add 'voting api percent vote value' field and filter,the result comes to empty.
I want to know vote value of each user...is this a kind of bug?

What should I do?

It works for D6, but now.....

I have setup and advanced review and rating system using this tutorial. (check this issue: http://drupal.org/node/430170). But how to display this using views?? Any ideas??

the 'this' link doesnt work

the 'this' link doesnt work for me

Drupaling along...
Balance Bikes Canada

I am trying to do the exact

I am trying to do the exact same type of thing (in Drupal 6), but with a few extras. It looks like the tutorial you linked will help, as I am trying to set up a review site for users to perform multi-axial reviews. My stipulations are:

1) I am going to have users be able to add a product (which I should be able easily do with permission settings). However, if they add a product, I would like them to have a review for it on the same screen, or as a required Step 2. Otherwise, I feel having them do two separate unlinked processes (part 1= click to create add a product, part 2 = click on a separate menu to review it), fewer people will do the first anyway. So it is almost like saying when somebody accesses the "product" node, I want the "review" node to actually integrate into it seamlessly.

2) It actually isn't a product I am reviewing, but a worksite, with a geographic location. As part of the product entry, I would like users to be able to put in at least a city and state, and optionally an address. What I would then like to do is have a searchable index, where users can search by geographic location (ie, within 50 miles of this zip code) to find a worksite. Therefore, any worksites entered by users, with reviews already, should come up with that search. Also, I would like to have a general directory, ie, by state, which I assume I could do with tagging, but would imagine there would be an easier way. I believe using the gmap module is part of that, but am not sure how to integrate that information with my "product" and search for "reviews."

Any ideas for either of these, or better places to post them (since it is related to the original question, but also goes off on a tangent?)

Good Question

Did you figure anything out? As I'm trying to figure out where to start when building a site where members rate agencies... and like your way of thinking... (STEP 1)

I followed the text tutorial

I followed the text tutorial from of the link to setup a single rating system.

However the result is the 'Product' average rating widget just display the last ’review‘ rating instead of average of all 'review' rating of a Product node.

Ideas

Hola, everyone.
Im kind of new to Drupal and i've tried every single solution i found at drupal.org to have a multi-axes fivestar-like widget but totally unsuccessful. However, i came up with this idea:
- we have fivestar source code
- we can duplicate this code naming 'fivestar2' to all references to 'fivestar' on the code when needed
- we can create a module named fivestar2 so we have 2 fivestar blocks.
- Then, we can create multiple fivestar blocks provided that we know what to change so that we have a fivestar2, 3 or 4
Maybe this idea is totally pointless but, having no vast knowledge on PHP, i thought it could be fine.
The thing is that i dont know how to do it right now but im just a beginner, someone else may be able to.

Allow Multiple Ratings

Is there a way to allow users to have multiple ratings without having the original rating being replaced by the new one. For example let says users are rating multiple instances of Product A. Product A can exist in different colors. The first time a user rated Product A was when he had it in color Blue (user inputs "Blue" in one of the fields created by CCK). The next time the user rates the same Product A, but he wants to do it for color "Green." This time, the user inputs "Green" in one of the fields created by CCK. So when the user is raiting for a different color of Product A, the original raiting shouldn't be override.

Rating as Sort Criteria under Views Module

I followed this tutorial on Multiple Voting Axis with my D6 site and everything was okay before I tried to add the rating result as Sort Criteria. I added "field_rate_reliability" and set it to "Descending", but the nodes (which are to be rated) aren't in order of the values. I also tried adding a relationship but the axis tag (like "reliability") didn't appear in the "Vote tag" list.
Does anyone know how to figure it out?

--PROBLEM SOLVED, Please disregard -- I was able to follow this tutorial and it is all working, however when I navigate to my target node, I only see the votes displayed, not the title and body of the reviews that I submitted with my vote. How can I see the node on top, the voting results, and the reviews threaded below? I appreciate any tips. Thanks!

So I'm only trying to do the

So I'm only trying to do the basic setup for single axis reviews. I can see the widget, I have the "add a new review" link, clicking the review link opens the CCK content type. Everything goes great until you try to save the review. When you do, it throws a parse error:

Parse error: syntax error, unexpected '<' in /var/www/html/el/elixirist.com/sites/all/modules/fivestar/fivestar_field.inc(144) : eval()'d code on line 1

BTW, the "<" the error is referring to on Line 1 is <?php

I copied everything exact with the exception of the D6 version in the tpl.php file.

Anyone have any help for this I'd greatly appreciate it.

[EDIT] It's actually saving after pressing save but you can't let users just get a parse error when they try to save so I still need a fix.

[EDIT CORRECTION] It's saving the review but not saving the rating. The review title, body, and stars appear but all the stars are blank as if there is no rating.

FYI in d7 this is not

FYI in d7 this is not neccessary anymore
take a look what ericdiuran wrote: http://drupal.stackexchange.com/questions/5463/how-to-correctly-configur...

About this page

Drupal version
Drupal 5.x

Site Building Guide

Drupal’s online documentation is © 2000-2013 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License. Comments on documentation pages are used to improve content and then deleted.