AJAX star rating plugin

3 : Model

By Michael Schneidt (schneimi)
In the days of social networks, you often want to give users the possibility to rate things and to show the average rating. The most common user interface implementation is a star rating system. This plugin offers you an easy, customizable way to enable your users to star rate any CakePHP model you want.
rating/models/ratings.php

Model Class:

<?php 
/**
 * Model for the AJAX star rating plugin.
 *
 * @author Michael Schneidt <michael.schneidt@arcor.de>
 * @copyright Copyright 2009, Michael Schneidt
 * @license http://www.opensource.org/licenses/mit-license.php
 * @link http://bakery.cakephp.org/articles/view/ajax-star-rating-plugin-1
 * @version 2.3
 */
class Rating extends RatingAppModel {
  var 
$name 'Rating';
  
  var 
$validate = array('user_id' => array('rule' => array('maxLength' => 36),
                                           
'required' => true),
                        
'model_id' => array('rule' => array('maxLength' => 36),
                                            
'required' => true),
                        
'model' => array('rule' => 'alphaNumeric',
                                         
'required' => true));
}
?>

rating/rating_app_model.php

Model Class:

<?php 
/**
 * AppModel for the AJAX star rating plugin.
 *
 * @author Michael Schneidt <michael.schneidt@arcor.de>
 * @copyright Copyright 2009, Michael Schneidt
 * @license http://www.opensource.org/licenses/mit-license.php
 * @link http://bakery.cakephp.org/articles/view/ajax-star-rating-plugin-1
 * @version 2.3
 */ 
class RatingAppModel extends AppModel {
}
?>

Page 4: View

Comments 1081

CakePHP Team Comments Author Comments
 

Comment

1 Super Cool!

Many thanks for this super cool plugin! Great job well done!

Thanks
Posted Jul 8, 2009 by Sola Ajayi
 

Comment

2 Little Help with Plugin Models

Hi, I have a little problem with rating plugin model content.

I keep getting model_id does not exist when I use a plugin model. I enter the model as 'Plugin.Model' eg. 'News.Article'

I've confirmed the model_id exists in d database, I've also tested the same code used in rating_controller->view()

$model = 'News.Article';
$modelInstance = ClassRegistry::init($model);
$modelInstance->id = '3ad66b8f-55ce-11de-bb54-9f1eb639fa3a';
var_dump($modelInstance->exists(true));

In my test, it returns true, but in the the rating_controller it returns false.

I'd really appreciate some help. Thanks in advance.
Posted Jul 9, 2009 by Sola Ajayi
 

Comment

3 Little Help with Plugin Models

Hi,

thx for your comment! I tried to reproduce your problem and created a dummy "news" plugin with a model "article" and also put an article with your uuid into the db "articles", but I didn't experience the problem. Your code snippet shows true on top of the ratings_controller->view().

Do you use the latest CakePHP release? Did you test it with the demo? Atm I have no other idea, but I will let you know if I come up with something.

Regards
Posted Jul 9, 2009 by Michael Schneidt
 

Comment

4 Little Help with Plugin Models

Hi,

I just tested it with the demo and I still get the same error. With models in app/models it works well.

I'm using cake 1.2.3.8166.

Here is how I called the rating plugin.

echo $this->element('rating', array('plugin' => 'rating',
'model' => 'News.Article',
'id' => $article['Article']['id'])
);
?>
Thanks for your help.
Posted Jul 10, 2009 by Sola Ajayi
 

Comment

5 Little Help with Plugin Models

Hi,

ok now I got it too and could figure it out. The problem is, that the sanitization encodes the incoming uuid, that's why the model_id is not found. Further more a rating cannot be saved in the ratings table, because the model_id is an integer field.

I will add the support in the next version, so long you can change the model_id from int to varchar and disable the encoding on Sanitize::clean (in view() and save()) as follows:


Sanitize::clean($id, array('encode' => false));

I really didn't think of uuids, so tanks for your comment.
Posted Jul 10, 2009 by Michael Schneidt
 

Comment

6 Little Help with Plugin Models

Thank you very much! It now works!
Posted Jul 10, 2009 by Sola Ajayi
 

Comment

7 Error when rating...

Hey, I am new to cake but managed to complete both tutorials (Blog & ACL). I also did install the rating plugin, which is displayed fine. But as soon as I want to rate the following error occurs:


Warning (512): DbAcl::check() - Failed ARO/ACO node lookup in permissions check.  Node references:
Aro: Array
(
    [User] => Array
        (
            [id] => 3
            [username] => test
            [group_id] => 2
            [created] => 2009-07-22 17:35:44
            [modified] => 2009-07-22 17:35:44
        )

)

Aco: controllers/Ratings/save [CORE/cake/libs/controller/components/acl.php, line 239]

Its seems to have something to do with the DBACl http://book.cakephp.org/view/644/Initialize-the-Db-Acl-tables but cannot really figure it our. Thanks for your help!
Posted Jul 22, 2009 by Robert
 

Question

8 Error when rating...

Hey, I am new to cake but managed to complete both tutorials (Blog & ACL). I also did install the rating plugin, which is displayed fine. But as soon as I want to rate the following error occurs:


Warning (512): DbAcl::check() - Failed ARO/ACO node lookup in permissions check.  Node references:
Aro: Array
(
    [User] => Array
        (
            [id] => 3
            [username] => test
            [group_id] => 2
            [created] => 2009-07-22 17:35:44
            [modified] => 2009-07-22 17:35:44
        )

)

Aco: controllers/Ratings/save [CORE/cake/libs/controller/components/acl.php, line 239]

Its seems to have something to do with the DBACl http://book.cakephp.org/view/644/Initialize-the-Db-Acl-tables but cannot really figure it our. Thanks for your help!
Posted Jul 22, 2009 by Robert
 

Question

9 re: Error when rating...

Hey, I am new to cake but managed to complete both tutorials (Blog & ACL). I also did install the rating plugin, which is displayed fine. But as soon as I want to rate the following error occurs:
....

I discovered the mistake myself. I did not have the permission to rate, so had to allow the ratings_controller.php to do this by adding:

        function beforeFilter() {
            parent::beforeFilter(); 
            $this->Auth->allowedActions = array('*');
        }
Posted Jul 22, 2009 by Robert
 

Comment

10 Good Job!

At a glance, seems to be a very nice plugin. Worked like a charm into my cake project. But there is some details that I would like to discuss.

1) Javascript need to be declared before the element instaciation: not a big deal, but i follow the Steve Souders´ performance tips, so, i prefer to declare my javascript on the end of document. Actually, it shows an error if I do this. A solution is simple - instead of call ratingInit directly, do this:


$(window).load(function() {
    renderInit( // arguments, etc..
}

So, the code will be executed after document load. If you have a public svn or git repo, i would like to help you with this.

Thx,

Yuri Teixeira.
Posted Aug 5, 2009 by Yuri Teixeira
 

Comment

11 Re: Good Job!

Thanks for your hint and solution, that makes sense and is no problem to change because it should work in each case. Only the code has to be moved inside the js-files because Prototype must be supported as well.

Maybe something like this:

rating_prototype.js

function ratingInit(element, data, options, config, enabled) {
  Event.observe(window, 'load', function() {
    ...
  });
}

rating_jquery.js

function ratingInit(element, data, options, config, enabled) {
  $(window).load(function () {
    ...
  });
}

Regards
Posted Aug 6, 2009 by Michael Schneidt
 

Comment

12 Re: Re: Good Job!

Sorry, forget about my last post, unfortunately that's not a solution because the window is only loaded once, meaning that there won't be further initialisations on the ajax updates that are important for an updated browser interface.

I currently see no way how to handle that, if you find something working let me know.
Posted Aug 10, 2009 by Michael Schneidt
 

Comment

13 Thanks!

Thanks for this great plug in!!!

I wanted to let you know that I found a little bug.

If you are using a custom primary key field in your model (not "id"), and you set Rating.saveAverageToModel to true, it won't work.

To make it work I just modified line 105 in ratings_controller.php from this:

$avgRating = $modelInstance->field(Configure::read('Rating.modelAverageField'), array($model.'.id' => $id));

to this:

$avgRating = $modelInstance->field(Configure::read('Rating.modelAverageField'), array($model.'.'.$modelInstance->primaryKey => $id));

Thanks again for sharing it! It saved me a lot of work :)

Nahuel
Posted Aug 12, 2009 by Nahuel
 

Comment

14 Images Missing

I'm having a problem where my Images go missing and instead of pointing at

user/rating/image/star-full.png

it now points at:-

user/rating/img/star-full.png

And when I click on a one of the image place holders I get this error:-

Error: The action rating is not defined in controller UserController

I assume I've missed something simple here since everyone else seems to get it working so easily. I'm using cake 1.2.5, and rating 2.0 with JQuery.

Anyone have any ideas what the problem could be ?
Posted Oct 3, 2009 by Steve
 

Comment

15 Re: Images Missing

The plugin uses the paths to the images that are set in the app/config/plugin.rating.php, default is "rating/img/star-full.png".

Where does the "user/" come from in your case? I thought it is your appRoot, but in this case there shouldn't be the controller error.

Maybe it would help you to download the working demo and setup a similar configuration of your situation.
Posted Oct 4, 2009 by Michael Schneidt
 

Comment

16 flash msg

Wonderful plugin. Works perfectly.
The flash messages work very well too, although as I already have flash messages in my website, I end up with some general flash messages appearing in the ratings boxes instead of in the initial place where I put my $session->flash().

Would you have any suggestions on how to separate my own flash messages (and decide of the place in the view where it gets displayed), from the ratings flash?
Posted Oct 16, 2009 by Julien Brinas
 

Comment

17 Re: flash msg

Thx for your comment, I really forgot about this scenario.

To solve the flash collisions you simply have to use a flash key, as shown in the following code.

rating\controllers\ratings_controller.php line 258

$this->Session->setFlash(Configure::read('Rating.flashMessage'), 
                         'default', 
                         array('class' => 'rating-flash'),
                         'rating');

rating\views\ratings\view.ctp line 95

$session->flash('rating');

Because of ajax reloading, the flash message element has to be within the plugin's view and cannot be placed elsewhere in your view. However it may help you to relocate the div.rating-flash via css in the rating\vendors\css\rating.css
Posted Oct 16, 2009 by Michael Schneidt
 

Comment

18 Re: Re: flash msg

To solve the flash collisions you simply have to use a flash key, as shown in the following code.
Works like a charm. Thanks!
Posted Oct 17, 2009 by Julien Brinas
 

Comment

19 lot of thx

very nice script ...
very useful...
Posted Oct 23, 2009 by satish
 

Bug

20 Problem loading config values - SOLVED

This was the first plugin I've ever installed, so I expected some hiccups.

My biggest (only) problem was that I didn't copy the plugin.rating.php config file into /app/config/plugin.rating.php

None of the Rating config values were set. All were NULL. I wasn't expecting to have to copy config files around. I thought I was diligent about reading the docs, but I must have missed something.

If for no other reason that to make me look foolish, could someone post a link to the documentation that says to copy the config file?

In addition, I think there is a 'bug' in the RatingsController where it loads the config file.

Check this out from line 45 in the RatingsController:

// load config    
    if (Configure::load($config) === false && Configure::read('Rating.showHelp')) {
      echo 'Error: The '.$config.'.php was not found in your app/config directory. Please copy it from rating/config/plugin.rating.php';
      exit;
    }

Is the logic really saying if I can't load the config file AND the config value to display help is true, then display an error message?

It would seem correct to remove the AND showHelp part of the logic. Yes?
Posted Oct 28, 2009 by Janice O'Toole
 

Comment

21 Re: protoaculous

Hi Seven,

find ich toll, dass du im Rahmen der FH die Möglichkeit hast CakePHP zu verwenden.

Das Plugin hat als Grundvoraussetzung dass entweder Prototype oder jQuery geladen ist, steht auch oben unter Requirements. Ist aber zugegeben etwas kurz und natürlich nicht klar was man machen muss, wenn man die beiden Frameworks gar nicht kennt. Werde ich mal überarbeiten, danke auf jeden Fall für das Feedback.

Gruß,
Michael
Posted Oct 28, 2009 by Michael Schneidt
 

Comment

22 Re: Problem loading config values

Hi Janice

somehow you missed step 3 in the installation instructions in this article as well as in the install.nfo file. Anyway, I aggree that the plugin could load some default configurations when there is no config file found.

There should be an error message, but as you correctly found out, the condition is crap, to read the showHelp config doesn't make any sense when there are no configs loaded. ;-)

Thx for that!
Posted Oct 28, 2009 by Michael Schneidt
 

Question

23 vertical to horizontal layout

Thanks for the plugin! I've got it working but just wondering why its layed out vertically? maybe this is related to my other css? I couldn't see a setting about this anywhere.
Posted Nov 9, 2009 by Jason
 

Comment

24 Re: vertical to horizontal layout

Someone else had this problem with using the cake.generic.css, where labels are declared as block elements. This is already fixed for the next version, so long you can just change/add the following parts in the rating\vendors\css\rating.css:

div.fallback label {
  display: inline;
  .
  .
}
div.rating label {
  display: inline;
}
Posted Nov 10, 2009 by Michael Schneidt
 

Bug

25 Problems with custom routes

Hi Michael,

there should be an error in the redirect with custom routes (named controllers) after saving the rate.

Example:
Router::connect(
    '/government',
    array('controller' => 'products', 'action' => 'display', 5)
);

There return an error view by calling the XMLHttpRequest.responseText…
Posted Nov 11, 2009 by malte
 

Comment

26 bugfix in js

it must be an absolute path in rating_jquery.js (line:132)… did you have a better solution? By exampe when the "appRoot" path is define by "/my_path/"…


url: ratingSettings[element]['config']['appRoot'] + '/rating/ratings/save/' + data[0] + '/' + data[3] + '/' + value + '?' + Math.floor(Math.random() * 999999),
Posted Nov 11, 2009 by malte
 

Comment

27 Great work! ...

Hello Michael, hello Cakebakers,

first of all i wish to thank Michael for this awesome piece of code.

Got it, had to use the element like this:

<?php
echo $this->element('rating', array('plugin' => 'rating',
                                    
'model' => 'Provider',
                                    
'id' => $provider['Provider']['id']));
?>

Just can repeat myself: Great work! Thanks a lot.
Posted Nov 20, 2009 by Daniel
 

Comment

28 If you have custom catchall routes

If you are overriding the default catchall route (/:controller/:action), here is a route to get you to the controller:

Router::connect('/rating/ratings/:action/*', array('controller' => 'ratings','plugin'=>'rating'));
Posted Nov 25, 2009 by Sequoia McDowell
 

Comment

29 "field ambiguous" error thrown for "view" method

Controller Class:

<?php 
//      $values = $modelInstance->find(array($modelInstance->primaryKey => $id), //causes "field 'id' is ambiguous" warning 
//
//fix:
//
      
$values $modelInstance->find(array($modelInstance->name.".".$modelInstance->primaryKey => $id), 
array(
Configure::read('Rating.modelAverageField'), 
                                           
Configure::read('Rating.modelVotesField')),
                                     
null,
                                     -
1);
?>
Posted Nov 25, 2009 by Sequoia McDowell
 

Comment

30 Not Working

Hi i am trying to integrate this plugin in my project, i dont have any problem in the view , working fine. When i click on rating the ajax request is made to rating/ratings/save/. , having all the parameters in the url. but not updated in the database. after the request , the whole page is loading in that particular div. i dont know what is the page.

help me to crack

Thanks in Advances..
Posted Nov 26, 2009 by Madhan
 

Comment

31 RE: Not Working

Looks like another routing problem. Maybe what Sequoia wrote in comment 29 could help you.
Posted Nov 27, 2009 by Michael Schneidt
 

Question

32 Use Auth component

how i can integrate with cake auth component

$config['Rating.sessionUserId'] = 'Auth.User.id';

does not work for me

Every time a see: Warning: No valid user id was found at "Auth.User.id" in the session
Posted Dec 6, 2009 by Bruno Trazzini
 

Comment

33 Re: Use Auth component

It works for me using Auth.User.id. If you aren't logged in you'll get that warning if you have it set to not allow guests, and you have the help text turned on in your settings.

If that warning goes away once you log in, then just turn off the help text in the plugin's config file.

Posted Jan 4, 2010 by Tony Maro
 

Comment

34 stars disappear

I am using jquery 1.1.4 minified and have set this plugin up according to the directions. However, when my page loads I can see the stars for a split second then they disappear and the rating status text is all that is left.

When I disable javascript I see the star ratings, status text, radio buttons, vote button, and mouseover messages. Also, when javascript is disabled I can vote and it works fine, adding my vote to the database. So my guess is something is happening in the rating_query.js that fouls up the display.

Any thoughts on how to fix this would be greatly appreciated.
Posted Feb 5, 2010 by Foroct Fralion
 

Comment

35 Re: stars disappear

Check the appRoot setting in your config file, it is used in js along with the image locations to change the source of the images. If the source is wrong, the images set in the view disappear on js initialization.
Posted Feb 7, 2010 by Michael Schneidt
 

Comment

36 almost working

I had this working for about a minute but now when i go to rate something I get the following error
Error: The .php was not found in your app/config directory. Please copy it from rating/config/plugin.rating.php

and the containing div of my page content replicates itself in the ratings box, the same type error that comment 30 was having.

So I looked in my app/config directory and its in there. When i turn off javascript, the radio buttons show and I can rate something. I also investigated the fix used in comment 29 but that did not work and I got the same result.

Still trying to get this to work.
Posted Feb 24, 2010 by Foroct Fralion
 

Comment

37 Re: almost working

Seems like the config parameter is not reaching the save method. I think it has something to do with the point in "plugin.rating", maybe you parse such extensions in your app.

I should change this, so long you could try to change the filename to maybe plugin_rating.php and change the default config in the rating element as well.
Posted Feb 24, 2010 by Michael Schneidt