验证在唯一约束中失败
Validation fails in Unique constraint
我正在使用 Laravel 的 Validator
class 验证一个简单的表单。
在我的用户模型中,我将此函数创建为 return 具有验证规则的数组:
/** 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 控制器,因此,当我执行方法 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 忽略此电子邮件和用户名,但验证器失败,说给定的用户名和电子邮件已经存在。
我做错了什么?
您对 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\''
此查询将 return 1,表示已找到记录且新数据不是唯一的(未通过唯一验证)。
如果您要通过引用传递给规则的值来解决这个问题,您的查询将最终成为:
select count(*) as aggregate from `user` where `username` = 'vitorluis' and `username` <> 'vitorluis'
显然,此查询始终 return 0,因此无论您将用户名更改为什么值,它始终会通过唯一规则。
您真正想要做的是确保您分配的用户名对于每条记录都是唯一的,除了您当前正在更新的一条记录。为此,您将当前正在更新的记录的 ID 传递给验证规则,以便它可以创建正确的查询。假设您正在更新 ID 为 10 的记录:
select count(*) as aggregate from `user` where `username` = 'vitorluis' and `id_user` <> 10
编辑
根据评论进行编辑
如果id字段不是id
,可以使用第四个参数给unique规则指定id字段。我已经更新了上面的代码以使用您的 id 字段名称 id_user
.
Laravel 可以找到唯一规则的文档 here。
我正在使用 Laravel 的 Validator
class 验证一个简单的表单。
在我的用户模型中,我将此函数创建为 return 具有验证规则的数组:
/** 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 控制器,因此,当我执行方法 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 忽略此电子邮件和用户名,但验证器失败,说给定的用户名和电子邮件已经存在。
我做错了什么?
您对 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\''
此查询将 return 1,表示已找到记录且新数据不是唯一的(未通过唯一验证)。
如果您要通过引用传递给规则的值来解决这个问题,您的查询将最终成为:
select count(*) as aggregate from `user` where `username` = 'vitorluis' and `username` <> 'vitorluis'
显然,此查询始终 return 0,因此无论您将用户名更改为什么值,它始终会通过唯一规则。
您真正想要做的是确保您分配的用户名对于每条记录都是唯一的,除了您当前正在更新的一条记录。为此,您将当前正在更新的记录的 ID 传递给验证规则,以便它可以创建正确的查询。假设您正在更新 ID 为 10 的记录:
select count(*) as aggregate from `user` where `username` = 'vitorluis' and `id_user` <> 10
编辑
根据评论进行编辑
如果id字段不是id
,可以使用第四个参数给unique规则指定id字段。我已经更新了上面的代码以使用您的 id 字段名称 id_user
.
Laravel 可以找到唯一规则的文档 here。