Автор:
Макаров Александр
20-го декабря нашёл в коде досадный недочёт: проверка на уникальность срабатывала при редактировании записи. Исправил.
Меня очень напрягало в Cake 1.1 то, что не было никаких средств проверки поля модели на уникальность. В Cake 1.2 добавили isUnique, но вот только забыли про то, что хорошо бы было добавить ещё один магический массив вроде $validate в модели.
Я решил исправить этот недостаток:
<?php
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.
Теперь в наших моделях можно проделать вот такую-вот штуку:
<?php
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('Сохранить');?>
Также можно производить проверку на уникальность по нескольким полям или по группе полей:
<?php
var $unique = array('title', 'text');
//или
var $unique = array('title', array('firstname', 'lastname'));
?>
Соответственно в View код для второго случая будет выглядеть так:
<?=$form->error('Post/unique_firstname_lastname', 'Уже есть такой автор!');?>
Спасибо за полезность! Но я так и не понял код для 1.1 или 1.2 (с 1.2 не работал).
судя по используемому хелперу форм 1.2
Спасибо автору, действительно полезный код, к тому-же его можно использовать и при построении списков уникальных значений таблицы в случаях когда значения могут повторятся.