Hello Yii-ers,
I have a model for reviews. There should be only one review per object per user. I have a joiner table with:
review_id, user_id, parent_id
review_id is the id of the users review
user_id is the users id
parent_id is the article id the user reviewed
I then set the following validation rule in the review model:
array(‘id’,‘DuplicateReview’),
Then created a custom validator:
/**
* Duplicate Review Validator
* @param string $attribute the name of the attribute to be validated
* @param array $params options specified in the validation rule
*/
public function DuplicateReview($attribute,$params)
{
$count = Blog::model()->checkReviewAbility($this->parent_id);
if($count->ability > 0)
{
$message = Yii::t('Review.Model', 'Thank you for your review! But, you have already added a review for ' . $this->title . '.');
$this->addError($attribute, $message);
}
}
The checkReviewAbility function is in the blog model and has the following code:
/**
* Check to see if user has already added a review for this object
*/
public function checkReviewAbility($parentId = 0)
{
$command = Yii::app()->db->createCommand()
->select('count(*)as ability')
->from('{{review_user}}')
->where('parent_id=:parentid and user_id=:userid', array(':parentid'=>$parentId, ':userid'=>Yii::app()->user->id))
->queryRow();
return $command;
}
What I am trying to accomplish is when a user goes to add a new review checkReviewAbility should be called. If it returns 0 then this user hasn’t reviewed this article and it should save. If checkReviewAbility > 0 then the user has already reviewed this article and they should be presented with an error message.
I’m trying to go about this using a test method to try and create duplicate reviews. Having the first one succeed and the second one fail.
I created the following test:
<?php
class ReviewTest extends CDbTestCase
{
//fixture connection
public $fixtures=array(
'blogs'=>'Blog',
'comments'=>'ReviewComment',
'reviews'=>'Review',
'users'=>'User',
'authAssign'=>':AuthAssignment',
);
public function testCreateArticleReview()
{
//insert a new review on an article
$review = new Review();
$review->setAttributes(array(
'parent_id'=>1,
'title'=>'Article Review',
'content'=>'I liked this a lot',
'status'=>Review::STATUS_PENDING,
'rating'=>5,
//'create_user_id'=>1
//'create_time'=>time(),
//'update_user_id'=>'',
//'update_time'=>'',
));
Yii::app()->user->setId($this->users('user1')->id);
$this->assertTrue($review->save());
}
public function testDuplicateReview()
{
//tries to enter a review for user and parent id that already exists.
// The save should be false based on duplicateReview validator
$review = new Review();
$review->setAttributes(array(
'parent_id'=>1,
'title'=>'Article Review2',
'content'=>'I liked this a lot2',
'status'=>Review::STATUS_PENDING,
'rating'=>5,
//'create_user_id'=>1
//'create_time'=>time(),
//'update_user_id'=>'',
//'update_time'=>'',
));
Yii::app()->user->setId($this->users('user1')->id);
var_dump(Blog::model()->checkReviewAbility(1));
$this->assertFalse($review->save());
}
}
When I var_dump the array shown has
array(1) {
["ability"]=>
string(1) "1"
}
so, this is greater then 1. So, the save should fail on validation on the second save (testDuplicateReview). But it asserts true and further more it seems to update/overwrite the original review.
I honestly have no idea what I am doing wrong. If my checkReviewAbility is written correctly or if it is the validator that is wrong.
Any help would be much appreciated!
Thank you!