2

Доброго времени суток!

Есть таблица с индексом уникальности сразу по двум полям:

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) -- индекс
);

Как в CActiveRecord::rules() для поля title создать правило unique чтобы уникальность проверялась на по всей таблица, а, именно, в рамках значения id_field?

UPD: Рабочий код

// 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)); } }

KiTE
  • 8,180
  • несовсем понял, вам нужно чтоб в таблице не повторялся title при равных равных значениях поял id_field? – Ale_x Aug 20 '12 at 15:03
  • Проверяться должна уникальность комбинации id_field и title – KiTE Aug 20 '12 at 15:04

1 Answers1

3

Как я вас понял, поле title не должно повторятся при одинаковых значениях поля id_field. Если я правильно понял, попробуйте так, должно сработать (я давно такое делал), исходников нет под рукой, если не заработает, поправим.

В модели

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)); } }

Nicolas Chabanovsky
  • 51,426
  • 87
  • 267
  • 507
Ale_x
  • 6,158
  • Получается, что решается только через кастомный валидатор?

  • Не понял, зачем разные валидаторы для add и edit?

  • И в чем смысл id_field!=:id_field?

    – KiTE Aug 20 '12 at 15:28
  • add - сценарий добавления, то есть нельзя создать запись в базе если вней уже присутствует то же самое сочетание id_field и title.

    edit - редактирование записи. Представь что ты отредактировал все но сочетание id_field и title не изменил, то предыдущий валидатор, составленный только для add тебя не пропустит

    – Ale_x Aug 20 '12 at 15:35
  • Посмотрел исходник CUniqueValidator. Оказалось что там есть проверка на то, когда добавляется новая запись и когда меняется существующая. Поэтому первый валидатор пропустит изменение.

    Но в целом понятно, спасибо.

    – KiTE Aug 20 '12 at 16:31
  • Хм... Попробуйте, у меня измения не пропустил( – Ale_x Aug 20 '12 at 16:52
  • Я проверил перед тем как комментить. У меня все работает с одним валидатором. Тестил на 1.1.12. Хотя, судя по гитхабу, последние существенные изменения в этом классе делались очень давно. – KiTE Aug 20 '12 at 17:01
  • ваще интересно стало. А код изменения записи можно привести?- уже спортивный интерес)) – Ale_x Aug 20 '12 at 17:03
  • Без проблем. Добавил в топик. – KiTE Aug 20 '12 at 17:32
  • я по другому делал изменение, поэтому походу и не срабатывало) попытаюсь завтра исходник найти - глянуть – Ale_x Aug 20 '12 at 17:48