CUniqueValidator with Criteria

Table attribute_option:






I want to ensure that ‘value’ is unique based on attribute_id column.

Model AttributeOption:

array('value', 'unique', 'criteria'=>array(





$model=new AttributeOption;








		$this->redirect(array('options', 'id'=>$model->attribute_id));


This doesn’t work for me, I can insert duplicate ‘value’ and it goes through.

to solve this problem just setup in your myphpadmin sql table index key that value in table attribute_option is unique,

EDIT: and in your model when you fill your table setup that property in rules to unique

But ‘value’ is only unique based on the attribute_id

So this is all valid:

attribute_id   value

1               1

1               2

2               1

2               2

But this is not valid:

attribute_id   value

1               1

1               1

2               2

2               2

then you have to setup where is unique

array('value', 'unique', 'on'=>'attribute_id'),

EDIT: Sory thats scenario ,

EDIT try this this should be work couse you can setup condition on unique value

array('value', 'unique', 'condition'=>'attribute_id = :attribute_id'),

I already tried that (check my original post)

Anybody got any suggestions?

I have never used that G,

For comparisons I use client checking and onBeforeSave to check for the attributes:

public onBeforeSave(){


   if (parent::beforeDelete()){

     if($model->attribute_id == $model->value) 


      // write error to Model

      $model->addError('attribute_id', 'value and attribute_id cannot be the same');

      return false;


     return true;


   return false;



In phpmyadmin, first remove unique from attribute_id, then tick both attribute_id and value columns, and click make unique icon.

in Yii, try this:

array('value, attribute_id', 'unique')

Cheers Antonio, I might have to do it that way but I don’t know why it doesn’t work in the rule - the ‘criteria’ option is provided so that we can define a criteria for the rule to work with. I must be doing something incorrectly somewhere.

I have just done some testing - in my rule that I have posted at the top, if I hardcode in a value, eg:


Then the rule works. So it does not seem to be understanding/capturing $this->attribute_id

mmm… that is interesting G, that may have something to do with object lifecycle, that is, the attribute is not yet set.

I look around for my side. I would like to do some research before I post, let me know if you find something as I am interested in this solution.


After doing some research I am thinking that what you don’t want is that attribute_id is not equal a value right? Then, why don’t you use CCompareValidator instead?

array('attribute_id', 'compare', 'compareAttribute'=>'value', 'operator'=>'!=')

Hi Gstar

$this->attributeId cannot find in the rules of validator, because they are parsed when the object is created.

I always used the validator without condition, and all was working fine.

Can you explain why exactly you need a condition? What is the behavior you are looking for?

Antonio - no that’s not correct.

This is exacttly what I’m trying to acheive:

let me check…

attribute_id operator value

1 = 1 <--------- so if attribute_id = value is correct?

1 != 2 <--------- so if attribute_id != value is correct?

2 != 1 <--------- attribute_id != value is correct?

2 = 2 <---------- attribute_id = value

Please excuse me G, I am a bit confused.

Lol this isn’t as complicated as it seems. attribute_id is just a parent of value. We are not doing a comparison between attribute_id and value. This might be more helpful:

This is all valid:

attribute_id   value 

1               Dog 

1               Cat 

2               Dog 

2               Cat

This is not valid:

attribute_id   value 

1               Dog 

1               Dog 

2               Cat 

2               Cat

Basically the user cannot enter Dog or Cat twice for the same attribute_id.

Duh! :D ok, now I understand…

But G, can’t you do that on the client? I see this is more like the way you print the form to the user and how it is posted.

Let me explain, I know that I have certain Dogs and Cats (lol) that I can select for a Model right? Then when I display the ‘insert new Model’ I just display those not in relation with Model to be updated. I do not know if I explain my self clearly.

I do this constantly and it works very well, on create I show a list box of the VALUES it can select (checkboxes, listboxes, whatever) on create is easy.

Now on update, I display the VALUES that it has and the possible VALUES he can select. This is now pure javascript, If a user removes an attribute that it has, then list box with possible VALUES to select are updated. On submit, relations are re-created before saving.

If I have Cats, then I display Cat as selected VALUE and Dogs as possible addition to the Model.

Maybe it is too complicated -I come with strong JS background, or my english is very poor, but this is how I do it in these cases.

Antonio - there is no predefined list of values. This functionality is just to ensure that the user does not accidentally enter the same value twice, for the same attribute_id.

P.S. Nothing wrong with your English - it’s very good!

Then, and by taking into account zac’s comment on this matter I think that a check onBeforeSave using ADO should be the correct way my friend.

Apologies for not being a better help and for making some Hommer Simpson understanding mistakes dough!

Cheers G

I managed to resolve this by creating my own validation function (not sure why I didn’t think of that before!).

Anyway do you think this is a problem with the CUniqueValidator, or is it never expected to work this way? How I see it is that there is a criteria option provided for this very purpose - all I have done in my custom function is to specify the criteria.

You can simulate that same functionality in MySQL, by setting (attribute_id,value) as your primary key, auto_increment value.

This only works in MySQL’s MyISAM engine, it does not work as expected in InnoDB.


  `parent_id` int(10) unsigned NOT NULL,

  `child_id` int(10) unsigned NOT NULL AUTO_INCREMENT,

  PRIMARY KEY (`parent_id`,`child_id`)


Hello G, please tell me how u are manage this criteria in your custom validation class.