多次扩展 Laravel 验证器
Posted
技术标签:
【中文标题】多次扩展 Laravel 验证器【英文标题】:Extend Laravel validator multiple times 【发布时间】:2014-04-29 11:29:14 【问题描述】:类似于confirmation
规则,我正在创建一个基于另一个属性值的验证规则。据我所知,实现这一点的唯一方法是扩展 Validator 类并通过$this->data
获取值。
文档说扩展验证器,然后使用Validator::resolver
注册新的扩展类。这工作正常,但仅在单个解析器的情况下,因为似乎每个后续定义的解析器都简单地覆盖了前一个。
如何解决这个问题?我们如何定义仍然可以访问其他属性的自定义验证器而不将所有方法放在同一个类中......?
谢谢
//
注意:我问这个是因为我想发布一些验证器包,但是按照上面的推理,如果有人安装了多个包,它们就会变得毫无用处...... p>
【问题讨论】:
【参考方案1】:我将Illuminate\Validation\Factory
、Illuminate\Validation\ValidationServiceProvider
和Illuminate\Validation\Validator
分别分类为(例如)MyFactory
、MyValidationServiceProvider
和MyValidator
。
MyFactory.php 看起来像这样:
<?php
use Illuminate\Validation\Factory;
class MyFactory extends Factory
/**
* @inheritDoc
*
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return MyValidator
*/
protected function resolve(array $data, array $rules, array $messages, array $customAttributes)
if (is_null($this->resolver))
return new MyValidator($this->translator, $data, $rules, $messages, $customAttributes);
else
return call_user_func($this->resolver, $this->translator, $data, $rules, $messages, $customAttributes);
MyValidationServiceProvider.php 看起来像这样:
<?php
use Illuminate\Validation\ValidationServiceProvider;
class MyValidationServiceProvider extends ValidationServiceProvider
/**
* @inheritDoc
*
* @return void
*/
public function register()
$this->registerPresenceVerifier();
$this->app->bindShared('validator', function($app)
$validator = new MyFactory($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;
);
MyValidator.php 看起来像这样:
<?php
namespace MuThetaTau\MuThetaTau\Validation;
use Illuminate\Validation\Validator;
class MyValidator extends Validator
// custom validation logic
最后,我必须更新 app.php 中的服务提供者以指向 MyValidationServiceProvider' instead of
Illuminate\Validation\ValidationServiceProvider`。
外观Validator
现在指向MyValidator
。您甚至可以创建多个工厂,向MyValidationServiceProvider
添加(和调用)方法以注册其他验证器类以将新工厂映射到新的 IoC 绑定,创建新的外观类,并在应用程序的外观中添加条目.php 为您制作的每个验证器提供不同的外观。
【讨论】:
【参考方案2】:是的,它被覆盖的原因是Validator\Factory
类只存储了一个resolver
。该函数的代码在这里:
public function resolver(Closure $resolver)
$this->resolver = $resolver;
我认为resolver
方法的重点是用您自己的扩展基本验证类。这是有道理的,因为您可以实例化 UserRegistrationValidator
,添加您自己的验证规则,这些规则具有与现有规则一样的灵活性。
其中一个问题是它可以很容易地被覆盖,这向我表明你应该只在调用make
之前调用resolver
方法。尽管付出了更多努力,但它会阻止来自不同包的规则可能会自动覆盖其他规则,甚至是基本规则。
但这不适用于只提供额外有用规则的包。添加规则的更简单的版本是:
Validator::extend('foo', 'FooValidator@validate');
这不允许访问对复杂规则很重要的输入数据。 documentation 示例也向我们展示了这一点:
class CustomValidator extends Illuminate\Validation\Validator
public function validateFoo($attribute, $value, $parameters)
return $value == 'foo';
等一下!文档没有告诉您的是,您可以添加另一个参数来获取Validator
的实例。这是我在写这个答案并深入课堂时才发现的!
class TestRulesValidator
public function validateTestRule($attribute, $value, $params, $validator)
var_dump($validator->getData());
Validator::extend('test_rule', 'TestRulesValidator@validateTestRule');
总之,传递一个额外的参数,该参数将是正在使用的验证器的实例。我怀疑这也适用于回调。
希望这对我有帮助!
【讨论】:
一个非常全面的答案,我很感激。我不知道额外的$validator
参数,但它显然解决了问题。非常感谢!你刚刚成为我今天的英雄。
@Propaganistas 没问题 :)以上是关于多次扩展 Laravel 验证器的主要内容,如果未能解决你的问题,请参考以下文章