【问题标题】:Extend Laravel validator multiple times多次扩展 Laravel 验证器
【发布时间】:2023-03-04 22:28:01
【问题描述】:

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

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

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

谢谢

//

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

【问题讨论】:

    标签: php validation laravel package


    【解决方案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 没问题 :)
      猜你喜欢
      • 1970-01-01
      • 2021-06-07
      • 2014-11-06
      • 2019-09-09
      • 1970-01-01
      • 2018-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多