我正在使用Laravel的Validator
类验证一个简单的表单。
在我的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控制器,因此,当我执行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'''
此查询将返回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文档可以在这里找到。