多次扩展 Laravel 验证器

Posted

技术标签:

【中文标题】多次扩展 Laravel 验证器【英文标题】:Extend Laravel validator multiple times 【发布时间】:2014-04-29 11:29:14 【问题描述】:

类似于confirmation 规则,我正在创建一个基于另一个属性值的验证规则。据我所知,实现这一点的唯一方法是扩展 Validator 类并通过$this->data 获取值。

文档说扩展验证器,然后使用Validator::resolver 注册新的扩展类。这工作正常,但仅在单个解析器的情况下,因为似乎每个后续定义的解析器都简单地覆盖了前一个。

如何解决这个问题?我们如何定义仍然可以访问其他属性的自定义验证器而不将所有方法放在同一个类中......?

谢谢

//

注意:我问这个是因为我想发布一些验证器包,但是按照上面的推理,如果有人安装了多个包,它们就会变得毫无用处...... p>

【问题讨论】:

【参考方案1】:

我将Illuminate\Validation\FactoryIlluminate\Validation\ValidationServiceProviderIlluminate\Validation\Validator 分别分类为(例如)MyFactoryMyValidationServiceProviderMyValidator

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 ofIlluminate\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 验证器的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 字体扩展验证

Laravel 扩展规则消息

Laravel 4.x 关于扩展身份验证的文档是不是错误?

Laravel 5.5 文件扩展验证不起作用

Laravel:模型内的验证。多重验证规则

使用 Captcha 扩展包 为 Laravel 5 应用生成验证码