Good day!

There is a table with a unique index on two fields at once:

CREATE TABLE table_name( id INT(11) NOT NULL AUTO_INCREMENT, id_field INT(11) NOT NULL, title VARCHAR(255) NOT NULL, PRIMARY KEY (id), INDEX id_field (id_field), UNIQUE INDEX title (title, id_field) -- индекс ); 

As in CActiveRecord::rules() for the title field, create a unique rule so that uniqueness is checked on the entire table, but, exactly, within the limits of the id_field value?

UPD: Working code

 // Controller public function actionAction( $id_field,$id_item=null ) { // ... $item=null; if( $id_item!==null ) $item=FieldItem::model()->findByPk($id_item); if( $item===null ) $item=new FieldItem(); if( isset($_POST['FieldItem']) ) { $item->attributes=$_POST['FieldItem']; $item->id_field=$id_field; if( $item->save() ) $this->redirect(/*...*/); } // ... } // FieldItem public function rules() { return array( //... array('title', 'uniqueTitle'), //... ); } public function uniqueTitle( $attribute,$params=array() ) { if( !$this->hasErrors() ) { $params['criteria']=array( 'condition'=>'id_field=:id_field', 'params'=>array(':id_field'=>$this->id_field), ); $validator=CValidator::createValidator('unique',$this,$attribute,$params); $validator->validate($this,array($attribute)); } } 
  • I do not quite understand, you need to ensure that the table does not repeat the title with equal equal values ​​of the id_field? - Ale_x
  • The unique combination of id_field and title should be id_field - KiTE

1 answer 1

As I understand you, the title field should not be repeated for identical values ​​of the id_field field. If I understand correctly, try this, it should work (I did this for a long time), the source code is not at hand, if it does not work, we'll fix it.

In the model

 public function rules() { array ( // невозможно создать элемент справочника с уже существующем именем array ( 'title', 'uniqueIdFieldAndTitleonAdd', 'on'=>'add', 'message'=>'запись с таким наименованием уже существует', ), //невозможно переименовать элемент в уже существующий array ( 'title', 'uniqueIdFieldAndTitleonEdit', 'on'=>'edit', 'message'=>'запись с таким наименованием уже существует', ) ) ); } public function uniqueIdFieldAndTitleonAdd($attribute,$params=array()) { if(!$this->hasErrors()) { $params['criteria']=array( 'condition'=>'id_field=:id_field', 'params'=>array(':id_field'=>$this->id_field), ); $validator=CValidator::createValidator('unique',$this,$attribute,$params); $validator->validate($this,array($attribute)); } } public function uniqueIdFieldAndTitleonEdit($attribute,$params=array()) { if(!$this->hasErrors()) { $params['criteria']=array( 'condition'=>'id_field!=:id_field', 'params'=>array(':id_field'=>$this->id_field), ); $validator=CValidator::createValidator('unique',$this,$attribute,$params); $validator->validate($this,array($attribute)); } } 
  • 1. It turns out that it is solved only through a custom validator? 2. I do not understand why different validators for add and edit ? And what is the meaning of id_field!=:id_field ? - KiTE
  • add - add script, that is, you cannot create an entry in the database if the same combination of id_field and title is already present. edit - edit the record. Imagine that you have edited everything but the combination of id_field and title did not change, then the previous validator composed only for add will not let you through - Ale_x
  • Looked source CUniqueValidator . It turned out that there is a check on when a new record is added and when the existing one changes. Therefore, the first validator will skip the change. But as a whole it is clear, thanks. - KiTE
  • Hmm ... Try it, I did not miss the change ( - Ale_x
  • I checked before commenting. Everything works for me with one validator. Testing on 1.1.12. Although, judging by the githab, the last significant changes in this class were made a very long time ago. - KiTE