Проверка не выполняется в ограничении уникальности

Я проверяю простую форму, используя Validator класс Laravel.

В моей модели User я создаю эту функцию для возврата массива с правилами проверки:

/** function to return the rules to validate a user */
    public static function rules($email = null, $username = null) {
        return array(
            "name" => "required",
            "username" => "required|unique:user,username" . ($username ? ",'$username',username" : ""),
            "email" => "required|email|unique:user,email" . ($email ? ",'$email',email" : ""),
        );
    }

Я использую RESTful Controller, поэтому, когда я выполняю метод update (), я проверяю данные формы с помощью массива выше.

Это мой массив после выполнения функции rules:

array (size=3)
  'name' => string 'required' (length=8)
  'username' => string 'required|unique:user,username,'vitorluis',username' (length=50)
  'email' => string 'required|email|unique:user,email,'[email protected]',email' (length=63)

Я говорю Laravel игнорировать этот адрес электронной почты и имя пользователя, но валидатор не работает, говоря, что данное имя пользователя и адрес электронной почты уже существуют.

Я что то не так делаю?


person Vitor Villar    schedule 07.03.2015    source источник


Ответы (1)


Вы немного неправильно поняли параметр id правила unique. Вам нужно передать идентификатор обновляемой записи, а затем указать уникальному правилу, чтобы исключить этот идентификатор записи.

// $id should be the string 'NULL' if no id passed in
public static function rules($id = 'NULL') {
    return array(
        "name" => "required",
        "username" => "required|unique:user,username,".$id.",id_user",
        "email" => "required|email|unique:user,email,".$id.",id_user",
    );
}

Объяснение

Для существующей реализации, если вы посмотрите журнал запросов (DB::getQueryLog()), вы увидите, что оператор, выполняемый для проверки вашего имени, будет выглядеть следующим образом:

select count(*) as aggregate from `user` where `username` = 'vitorluis' and `username` <> '\'vitorluis\''

Этот запрос вернет 1, что означает, что запись была найдена, а новые данные не уникальны (не проходят уникальную проверку).

Если бы вы решили одну проблему с цитированием значения, переданного правилу, ваш запрос в конечном итоге был бы таким:

select count(*) as aggregate from `user` where `username` = 'vitorluis' and `username` <> 'vitorluis'

Очевидно, этот запрос всегда будет возвращать 0, поэтому независимо от того, на какое значение вы изменили имя пользователя, он всегда будет передавать уникальное правило.

Что вы действительно хотите сделать, так это убедиться, что имя пользователя, которое вы назначаете, уникально для каждой записи, за исключением одной записи, которую вы в настоящее время обновляете. Для этого вы передаете правилу проверки идентификатор обновляемой в данный момент записи, чтобы оно могло создать правильный запрос. Предполагая, что вы обновляете запись с идентификатором 10:

select count(*) as aggregate from `user` where `username` = 'vitorluis' and `id_user` <> 10

Редактировать

редактировать из-за комментариев

Если поле id не id, вы можете указать поле id, используя четвертый параметр уникального правила. Я обновил приведенный выше код, чтобы использовать имя поля вашего идентификатора id_user.

Документацию Laravel для уникального правила можно найти здесь.

person patricus    schedule 07.03.2015
comment
Верно, Патрикус, но мой первичный ключ не id, это id_user. Как я могу сказать это в правилах массива? Я говорю вам это, потому что Laravel выдает такую ​​ошибку: Undefined column: 7 ERROR: column "id" does not exist - person Vitor Villar; 07.03.2015
comment
@VitorLuis Если у вас первичный ключ, отличный от id, вы можете передать его после значения ID. В данном случае: "username" => "required|unique:user,username,".$id.",id_user". - person Bogdan; 07.03.2015