duanbinian2243
duanbinian2243
2015-03-07 00:38

唯一约束中的验证失败

已采纳

I'm validating a simple form using Validator class of Laravel.

In my User model, i create this function to return an array with the validation rules:

/** 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" : ""),
        );
    }

I'm using an RESTful Controller, so, when i execute the method update(), i validate the form data with the array above.

This is my array after the rules function execution:

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)

I'm telling to Laravel ignore this email and username, but the Validator fails, saying the given username and email already exists.

I'm doing something wrong?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • dsdsds12222 dsdsds12222 6年前

    You've misunderstood the id parameter to the unique rule a little bit. You need to pass in the id of the record you're updating, and then tell the unique rule to exclude that record 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",
        );
    }
    

    Explanation

    For your existing implementation, if you were to look at your query log (DB::getQueryLog()), you would see that the statement run for your name validation would be:

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

    This query would return 1, meaning a record was found and the new data is not unique (fails the unique validation).

    If you were to fix the one issue with quoting the value passed to the rule, your query would then end up being:

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

    Obviously, this query would always return 0, so no matter what value you changed the username to, it would always pass the unique rule.

    What you're really wanting to do is to make sure that the username you're assigning is unique to every record except for the one record you're currently updating. To do this, you pass to the validation rule the id of the record you're currently updating, so it can create the correct query. Assuming you're updating a record with the id of 10:

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

    Edit

    edit due to comments

    If the id field is not id, you can specify the id field using the fourth parameter to the unique rule. I have updated the code above to use your id field name id_user.

    Laravel documentation for the unique rule can be found here.

    点赞 评论 复制链接分享