唯一约束中的验证失败

时间:2015-03-07 00:38:59

标签: php validation laravel

我正在使用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()时,我使用上面的数组验证表单数据。

这是规则函数执行后的数组:

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,'myemail@gmail.com',email' (length=63)

我告诉Laravel忽略此电子邮件和用户名,但Validator失败,说已经存在给定的用户名和电子邮件。

我做错了什么?

1 个答案:

答案 0 :(得分:2)

您误解了unique规则的id参数。您需要传入要更新的记录的ID,然后告诉唯一规则排除该记录ID。

// $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,因此无论您将用户名更改为什么值,它都将始终通过唯一规则。

您真正想要做的是确保您分配的用户名对于每个记录都是唯一的,除了您当前正在更新的一条记录。为此,您将验证规则传递给当前正在更新的记录的ID,以便它可以创建正确的查询。假设您正在更新id为10的记录:

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

修改

由于评论

编辑

如果id字段不是id,则可以使用唯一规则的第四个参数指定id字段。我已更新上述代码,以使用您的ID字段名称id_user

可以找到唯一规则的Laravel文档here