cakephp уникален для двух полей?
-
20-09-2019 - |
Вопрос
У меня есть регистрационная форма, в которой пользователи могут указать два адреса электронной почты (email1 и email2).Требование маркетинга заключается в том, что они должны быть уникальными (уникальными, например, если бы у нас было 10 пользователей, то было бы 10*2=20 уникальных адресов электронной почты).
Система уже построена на cakephp, поэтому мне хотелось бы знать, есть ли что-то похожее на функцию isUnique (уникальная в одном поле), которая может сделать это прямо из коробки?Или я обречен писать это сам?Заранее спасибо.
РЕДАКТИРОВАТЬ:построенный на примере Ричарда, у меня это сработало:
function checkUnique($data, $fields) {
if (!is_array($fields)) {
$fields = array($fields);
}
foreach($data as $key) {
$checks = $key;
}
if (empty($checks)) {
return true; //allow null
}
foreach($fields as $key) {
$tmp[$key] = $checks;
}
if (isset($this->data[$this->name][$this->primaryKey])) {
$tmp[$this->primaryKey] = "<>".$this->data[$this->name][$this->primaryKey];
}
return $this->isUnique($tmp);
}
Решение
Я опубликовал решение этой проблемы в группе Google CakePHP:
Добавьте в свою AppModel следующее:
/**
* checks is the field value is unqiue in the table
* note: we are overriding the default cakephp isUnique test as the
original appears to be broken
*
* @param string $data Unused ($this->data is used instead)
* @param mnixed $fields field name (or array of field names) to
validate
* @return boolean true if combination of fields is unique
*/
function checkUnique($data, $fields) {
if (!is_array($fields)) {
$fields = array($fields);
}
foreach($fields as $key) {
$tmp[$key] = $this->data[$this->name][$key];
}
if (isset($this->data[$this->name][$this->primaryKey])) {
$tmp[$this->primaryKey] = "<>".$this->data[$this->name][$this-
>primaryKey];
}
return $this->isUnique($tmp, false);
}
}
и используется в проверке вашей модели:
var $validate = array(
"name"=>array(
"unique"=>array(
"rule"=>array("checkUnique", array("name", "institution_id")),
"message"=>"A contact with that name already exists for that
institution"
)
)
);
Другие советы
checkUnique
можно просто написать как обертку для isUnique
.
class AppModel extends Model {
public function checkUnique($ignoredData, $fields, $or = true) {
return $this->isUnique($fields, $or);
}
}
и используется в проверке вашей модели:
public $validate = array(
'name' => array(
'unique' => array(
'rule' => array('checkUnique', array('name', 'institution_id'), false),
'message' => 'A contact with that name already exists for that
institution'
)
)
);
Вы можете проверить уникальность набора полей, указав несколько полей и установив для $or значение false:
public $validate = array(
'email' => array(
'rule' => array('isUnique', array('email', 'username'), false),
'message' => 'This username & email combination has already been used.'
)
);
Обязательно включите исходное поле в список полей при создании уникального правила для нескольких полей.
Если указанное поле не включено в данные модели, оно рассматривается как нулевое значение.Вы можете рассмотреть возможность пометки перечисленных полей как обязательные.
Да и нет.
Да, вам придется написать код самостоятельно, но в рамках компонента проверки CakePHP.
Компонент проверки имеет механизм, позволяющий настраивать правила проверки.По сути, вы помещаете имя функции в $validate (как обычно).Вам нужно определить функцию;в данном случае это довольно просто (просто выполните требование double isUnique).
http://book.cakephp.org/2.0/en/models/data-validation.html#custom-validation-rules
Рискуя получить удары по голове и плечам за предложение не-CakePHP Решение, позвольте мне представить следующее.
Создайте уникальный индекс в своей базе данных для любого количества столбцов, которое вам нужно.
Стандартный синтаксис SQL для этого:
create unique index {IndexName} on {Table} ({Column}, {Column}, ...)
Поместите команду «$this->Model->save()» внутри блока «try/catch».В блоке «catch» проверьте исключение для кода ошибки.В MySQL уникальным нарушением ключа является код ошибки 23000, но вы должны быть готовы и к другим возможным ошибкам.
Это быстро и просто и не требует подсчета круглых скобок массива.
Вам следует всегда В любом случае поместите код доступа к базе данных внутри блока «try/catch».Часть обработки исключений должна включать регистрацию любых неожиданных сообщений об ошибках.Вы не можете ожидать, что CakePHP сделает все для тебя.
Насколько я помню, для такого рода принудительного применения приходится использовать beforeSave
метод в модели.У меня было требование, чтобы у объекта был установлен хотя бы один из N fks, и я мог сделать это только таким образом.
Редактировать:пытаться эта тема чтобы посмотреть, решит ли что-нибудь вашу проблему.