Use Node Comment and Fivestar to Create Advanced Reviews

Last updated on
13 May 2020

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

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:

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:

$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:

$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

Help improve this page

Page status: No known problems

You can: