Joh*_*ean 14 php forms validation laravel laravel-4
我有一个基本表单设置允许用户更改他们的电子邮件地址,我在更改电子邮件之前正在对其进行以下验证:
// Set up the form validation
$validator = Validator::make(
Input::all(),
array(
'email' => 'email|unique:users',
'password' => 'required'
)
);
// If validation fails, redirect to the settings page and send the errors
if ($validator->fails())
{
return Redirect::route('settings')->withErrors($validator)->withInput();
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,但在此基本验证后,我想检查用户是否提供了正确的密码.为此,我正在使用Laravel的基本身份验证库执行以下操作:
// Find the user and validate their password
$user = Auth::user();
if (!Auth::validate(array('username' => $user->username, 'password' => Input::get('password'))))
{
die("failed to authenticate");
}
Run Code Online (Sandbox Code Playgroud)
而不是处理逻辑告诉用户他们的密码本身不正确,我宁愿只是在password输入中添加一个表单错误,所以它就像常规表单验证一样显示.像这样的东西:
if (!Auth::validate(array('username' => $user->username, 'password' => Input::get('password'))))
{
$validator->addError('password', 'That password is incorrect.');
return Redirect::route('settings')->withErrors($validator)->withInput();
}
Run Code Online (Sandbox Code Playgroud)
这样,我的密码输入旁边会显示错误的密码错误,看起来像是正确的表单验证.
我怎样才能做到这一点?
Bas*_*ann 33
见Darren Craig的回答.
但是实现它的一种方法.
// inside if(Auth::validate)
if(User::where('email', $email)->first())
{
$validator->getMessageBag()->add('password', 'Password wrong');
}
else
{
$validator->getMessageBag()->add('email', 'Email not found');
}
Run Code Online (Sandbox Code Playgroud)
Jus*_*tin 11
接受的答案有一个问题(在我看来,一般是Laravel的验证器) - 验证过程本身和验证状态检测合并为一种方法.
如果你盲目地从包中提交所有验证消息,那没什么大不了的.但是,如果您有一些额外的逻辑来检测验证器是否失败并执行其他操作(例如为当前验证的表单字段提供国际文本消息),那么您就遇到了问题.
示范:
// let's create an empty validator, assuming that we have no any errors yet
$v = Validator::make([], []);
// add an error
$v->errors()->add('some_field', 'some_translated_error_key');
$fails = $v->fails(); // false!!! why???
$failedMessages = $v->failed(); // 0 failed messages!!! why???
Run Code Online (Sandbox Code Playgroud)
也,
$v->getMessageBag()->add('some_field', 'some_translated_error_key');
Run Code Online (Sandbox Code Playgroud)
产生相同的结果.为什么?因为如果你查看Laravel的Validator代码,你会发现以下内容:
public function fails()
{
return ! $this->passes();
}
public function passes()
{
$this->messages = new MessageBag;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,fails()方法基本上清除了丢失所有附加消息的包,从而使验证器认为没有错误.
无法将错误附加到现有验证器并使其失败.您只能使用以下自定义错误创建新的验证程序:
$v = Validator::make(['some_field' => null],
['some_field' => 'Required:some_translated_error_key']);
$fails = $v->fails(); // true
$failedMessages = $v->failed(); // has error for `required` rule
Run Code Online (Sandbox Code Playgroud)
如果您不喜欢滥用required自定义附加错误的验证规则,则可以始终使用自定义规则扩展Laravel Validator.我添加了一个通用failkey规则,并以此方式强制执行:
// in custom Validator constructor: our enforced failure validator
array_push($this->implicitRules, "Failkey");
...
/**
* Allows to fail every passed field with custom key left as a message
* which should later be picked up by controller
* and resolved with correct message namespaces in validate or failValidation methods
*
* @param $attribute
* @param $value
* @param $parameters
*
* @return bool
*/
public function validateFailkey($attribute, $value, $parameters)
{
return false; // always fails
}
protected function replaceFailkey($message, $attribute, $rule, $parameters)
{
$errMsgKey = $parameters[0];
// $parameters[0] is the message key of the failure
if(array_key_exists($errMsgKey, $this->customMessages)){
$msg = $this->customMessages[$parameters[0]];
}
// fallback to default, if exists
elseif(array_key_exists($errMsgKey, $this->fallbackMessages)){
return $this->fallbackMessages[$parameters[0]];
}
else {
$msg = $this->translator->trans("validation.{$errMsgKey}");
}
// do the replacement again, if possible
$msg = str_replace(':attribute', "`" . $this->getAttribute($attribute)
. "`", $msg);
return $msg;
}
Run Code Online (Sandbox Code Playgroud)
我可以像这样使用它:
$v = Validator::make(['some_field' => null],
['some_field' => 'failkey:some_translated_error_key']);
$fails = $v->fails(); // true
$failedMessages = $v->failed(); // has error for `Failkey` rule
Run Code Online (Sandbox Code Playgroud)
当然,这仍然是解决问题的一种黑客方式.
理想情况下,我会重新设计验证明确分开状态检测的验证阶段(单独的方法validate()和passes()或更好isValid()),并添加方便的方法来手动故障与特定规则的特定领域.虽然这也可能被认为是hacky,但如果我们想要使用Laravel验证器不仅仅使用Laravel自己的验证规则,而且还有我们的自定义业务逻辑规则,我们别无选择.
用户 Matt K 在评论中表示,laravel 已经实现了验证钩子,这正是我们想要的:
$validator = Validator::make(...);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails()) {
// this actually runs! even if the original validator succeeded!
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
34685 次 |
| 最近记录: |