<rmcreative>

RSS

Cake PHP: Расширение модели для валидации уникальных полей

17 декабря 2007

Меня очень напрягало в Cake 1.1 то, что не было никаких средств проверки поля модели на уникальность. В Cake 1.2 добавили isUnique, но вот только забыли про то, что хорошо бы было добавить ещё один магический массив вроде $validate в модели.

Я решил исправить этот недостаток:

class AppModel extends Model {
    /**
     * Use the following syntax to define some unique constraints:
     * 
     * $unique = array(
     *   'field1',
     *      array('field2', 'field3')
     * );
     *
     * @var array
     */
    var $unique = array();
 
    /** 
     *    Checks unique constraints.
     * 
     *    @param array $params    Array consisting of "field" => "value" 
     *    @param int $id          PK of record being editited (optional)
     *    @return boolean          Validation passed?     
     */ 
    private function checkUnique(array $rules, $id=''){
        $isValid = true;
 
        // Set Recursive Seach mode. 
        $this->recursive = -1;
 
        foreach ($rules as $rule){
            // @var array $query Array to $this->hasAny() against 
            $query = array();
            if(!is_array($rule)){
                $query[$this->name . '.' . $rule] = $this->data[$this->name][$rule];
            }
            else{
                foreach($rule as $field){
                    $query[$this->name . '.' . $field] = $this->data[$this->name][$field];        
                }
            }       
 
            // Check to see if we need to query against an id 
            if (empty($id)){ 
                $query[$this->name.'.id'] = "!= NULL";
            }  
            else{ 
                $query[$this->name.'.id'] = "!= {$id}";
            }
            // Run the query. 
            if ($this->hasAny($query)) {
                if(!is_array($rule)){
                    $this->invalidate('unique_'.$rule); 
                    $isValid = false;
                }
                else{
                    $this->invalidate('unique_'.implode('_', $rule));
                    $isValid = false;
                }                
            } 
        }
        return $isValid; 
    }
 
    function beforeValidate(){
        // Unique Constraints Check
        return $this->checkUnique($this->unique, $this->id);
    }
}

Код кладётся в app_model.php в папку app.

Теперь в наших моделях можно проделать вот такую-вот штуку:

class Post extends AppModel {
    var $name = 'Post';
 
    var $validate = array(
                'title'  => VALID_NOT_EMPTY,
                'text'   => VALID_NOT_EMPTY
    );
 
 
    var $unique = array('title');
}

И в View сделать так:

<h1>Добавить новость</h1>
<?=$form->create('Post');?>
    <?=$form->hidden('Post/id');?>
    <?=$form->input('Post/title', array('size' => '40', 'label' => 'Заголовок: '))?>
    <?=$form->error('Post/unique_title', 'Уже есть новость с таким заголовком!');?>
 
    <?=$form->textarea('Post/text', array('rows'=>'10', 'label' => 'Текст: ')) ?>
 
<?=$form->end('Сохранить');?>

Также можно производить проверку на уникальность по нескольким полям или по группе полей:

var $unique = array('title', 'text');
//или
var $unique = array('title', array('firstname', 'lastname'));

Соответственно в View код для второго случая будет выглядеть так:

<?=$form->error('Post/unique_firstname_lastname', 'Уже есть такой автор!');?>

Комментарии RSS

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.