是否可以更改 Laravel 的验证器回调中的错误消息?
Posted
技术标签:
【中文标题】是否可以更改 Laravel 的验证器回调中的错误消息?【英文标题】:Is it possible to alter error message in Laravel's Validator callback? 【发布时间】:2013-08-03 21:30:24 【问题描述】:我有一个这样的自定义验证器设置:
Validator::extend('valid_username', 'ProfileController@valid_username');
然后我有以下处理验证的方法。它会检查用户名是否已存在以及用户名是否包含有效字符。
public function valid_username($attribute, $value, $parameters)
$u = User::where('username', $value)->get();
if ($u->count())
// here I would like to return "Username already taken."
return FALSE;
else if (preg_match("/^[A-Za-z0-9@\.\-_]+$/", $value))
return TRUE;
else
// here I would like to return "Username contains invalid characters."
return FALSE;
我想根据导致验证失败的错误来更改此验证器返回的错误消息。但是,我不知道该怎么做。在我的语言文件中,我为验证器设置了以下行:
"valid_username" => "This username is already taken or contains invalid characters."
Laravel 是否可以返回特定的错误消息?还是我必须将此验证拆分为两个自定义验证规则?在这种情况下这可能不是问题,但特别是如果涉及数据库访问,我更愿意在一个验证器中验证检索到的 Eloquent 模型,而不是两次实例化 Eloquent 对象。
【问题讨论】:
我也有同样的问题。我有一个自定义验证器,它使用一些复杂的解析逻辑来确定输入是否有效。错误消息需要具体说明问题所在,因为“解析失败”是无用的。我希望验证器可以返回一个字符串,而不仅仅是真/假。 是的,正是我想要的。在 CodeIgniter 中可以做到这一点。但是我还没有在 Laravel 中找到一种方法:( 【参考方案1】:查阅代码后,答案是“不是开箱即用”。但是,您可以扩展所有内容并使其工作。
这个过程,我目前没有时间完全做(对不起!),将创建一个扩展 Validator 的类,使该功能工作,然后使用一个新的ServiceProvider 用你自己的替换 Laravel 的$app['validator']
。
这个过程,更具体一点,是这样的:
<?php namespace MyLib\Validation;
class Validator extends \Illuminate\Validation\Validator
// Fancy validation logic to be able to set custom messages
然后,您需要扩展工厂以返回您的新验证器:
<?php namespace MyLib\Validation;
class Factory extends \Illuminate\Validation\Factory
// Change this method
/**
* Resolve a new Validator instance.
*
* @param array $data
* @param array $rules
* @param array $messages
* @return \MyLib\Validation\Validator
*/
protected function resolve($data, $rules, $messages)
if (is_null($this->resolver))
// THIS WILL NOW RETURN YOUR NEW SERVICE PROVIDER SINCE YOU'RE
// IN THE MyLib\Validation NAMESPACE
return new Validator($this->translator, $data, $rules, $messages);
else
return call_user_func($this->resolver, $this->translator, $data, $rules, $messages);
...最后,扩展 Validation 服务提供者,使用您的新工厂,然后将默认的 ValidationServiceProvider 替换为您自己的。
<?php namespace MyLib\Validation;
class ValidationServiceProvider extends \Illuminate\Validation\ServiceProvider
/**
* Register the service provider.
*
* @return void
*/
public function register()
$this->registerPresenceVerifier();
$this->app['validator'] = $this->app->share(function($app)
// THIS WILL NOW RETURN YOUR FACTORY SINCE YOU'RE
// IN THE MyLib\Validation NAMESPACE
$validator = new Factory($app['translator'], $app);
// The validation presence verifier is responsible for determining the existence
// of values in a given data collection, typically a relational database or
// other persistent data stores. And it is used to check for uniqueness.
if (isset($app['validation.presence']))
$validator->setPresenceVerifier($app['validation.presence']);
return $validator;
);
无论如何,这是使用您自己的代码扩展验证库的一种方法。我没有解决添加您自己的消息的问题,但是如果您可以阅读核心代码并了解如何添加该功能,这将向您展示如何使其在您的应用中运行。
最后一点:
你可能想看看 Laravel 如何使用 Database "stuff" within validation rules 处理 - 虽然这可能不会影响你的应用程序(除非它变得很大!)你可能想考虑使用某种 Repository pattern 并在你的 @987654328 中使用它@ 直接调用而不是 User
类。没必要,只是一个要检查的注释。
祝你好运,不要害怕RTFC!
【讨论】:
我应该提一下,如果您需要创建一个验证规则,该规则可能会根据值返回不同的验证消息,而您现在无法立即执行此操作,那么这很好。自定义验证消息是您可以开箱即用的东西,但它是有限的,并且不能在您的Validator::extend()
调用中完成。
嘿@fideloper,这看起来你真的知道你在说什么;)感谢您的详细回答!我一点也不害怕 RTFC,但我想在这个时候和应用程序的大小上,它可能有点矫枉过正而且太费时了。所以我现在将使用 KISSable 解决方案。如果我需要更多地扩展和自定义验证器,这肯定会有所帮助。再次感谢!【参考方案2】:
您可以使用unique
规则,然后制定自己的规则来验证字符,而不是制定自己的验证规则来验证两件事(您不应该这样做,一次验证一件事)用户名。
例如:
$rules = ['username' => 'required|username|unique:users,username'];
username
规则是您的自定义规则,可确保它包含正确的字符。
【讨论】:
它并不能完全解决我交替消息输出的问题,但我同意在这种情况下将其拆分并使用唯一验证规则是有意义的。谢谢,杰森!【参考方案3】:也许有点“脏”,但它有效:
控制器用某些东西验证输入
$rules = array(
'title' => 'no_collision:'.$input['project_id']
);
在验证器函数中,在返回 false 之前将消息闪烁到 Session:
//...
public function validateNoCollision($attribute, $value, $parameters)
$project = Project::find($parameters[0]);
if($value == $project->title)
Session::flash('colliding_message','This collides with '.$project->title($).' created by '.$project->user->name;
return false;
else
return true;
在视图中执行以下操作:
@if($errors->has('title'))
<span class="help-block"> Session::get('colliding_message') </span>
@endif
【讨论】:
以上是关于是否可以更改 Laravel 的验证器回调中的错误消息?的主要内容,如果未能解决你的问题,请参考以下文章