与confirmation
规则类似,我正在创建一个基于另一个属性值的验证规则。根据我的发现,实现这一目标的唯一方法是扩展Validator类并通过$this->data
获取值。
文档说要扩展Validator,然后使用Validator::resolver
注册新的扩展类。这样可以正常工作,但仅限于单个解析器,因为似乎每个后续定义的解析器都会覆盖前一个解析器。
如何解决这个问题?我们如何定义仍然可以访问其他属性的自定义验证器,而不是将所有方法放在同一个类中......?
由于
//
注意:我问这个是因为我想发布一些验证程序包,但是按照上面的推理,如果有人安装了多个软件包,它们就变得毫无用处......
答案 0 :(得分:8)
是的,它被覆盖的原因是Validator\Factory
类只存储一个resolver
。该函数的代码如下:
public function resolver(Closure $resolver) {
$this->resolver = $resolver;
}
我认为resolver
方法的要点是使用您自己的方法扩展基本验证类。这是有道理的,因为您可以实例化UserRegistrationValidator
添加您自己的验证规则,这些规则具有与现有验证规则一样的灵活性。
这个问题的一个问题是它可以轻松覆盖,这表明你应该只在调用resolver
之前调用make
方法。虽然付出了更多的努力,但它会阻止来自不同软件包的规则,这些规则可能会自动覆盖其他规则甚至是基础规则。
但是这对于仅提供额外有用规则的包不适用。添加规则的更简单版本是:
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');
总而言之,传递一个额外的参数,该参数将是正在使用的验证器的实例。我怀疑这也适用于回调。
希望这有帮助,它确实适合我!
答案 1 :(得分:0)
我将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绑定,创建新的外观类,并向外墙添加条目在app.php中为每个验证器设置不同的外观。