接受的答案(在我看来,以及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???
也
$v->getMessageBag()->add('some_field', 'some_translated_error_key');
产生相同的结果。为什么?因为如果你查看Laravel的验证器代码,你会发现以下内容:
public function fails()
{
return ! $this->passes();
}
public function passes()
{
$this->messages = new MessageBag;
如您所见,方法基本上清除了丢失您附加的所有消息的包,从而使验证程序假设没有错误。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
如果您不喜欢滥用自定义附加错误的验证规则的想法,您可以随时使用自定义规则扩展Laravel Validator。我添加了一个通用规则,并以这种方式使其成为强制性的:required
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;
}
我可以这样使用它:
$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
当然,这仍然是解决问题的一种黑客方式。
理想情况下,我会重新设计验证器,以将其验证阶段与状态检测(单独的方法和/或更好)明确分开,并添加方便的方法以手动失败具有特定规则的特定字段。虽然这也可能被认为是黑客,但是如果我们不仅想将Laravel验证器与Laravel自己的验证规则一起使用,而且还要使用我们的自定义业务逻辑规则,我们仍然别无选择。validate()
passes()
isValid()