【问题标题】:Laravel 5.2 - extending the Validator classLaravel 5.2 - 扩展 Validator 类
【发布时间】:2016-07-23 03:54:19
【问题描述】:

我正在尝试覆盖Illuminate\Validation\Validator 中的doReplacements 方法。当我扩展本机 ValidatorRequest 类时,我收到此错误:

Route.php 第 270 行中的反射异常:

类 App\Http\Requests\FooRequest 不存在

这就是我所做的:

  1. 扩展原生Illuminate\Validation\Validator:

    class MyCustomValidator extends Validator {
    
        protected function doReplacements($message, $attribute, $rule, $parameters) {
            //override this method
        }
    
    }
    
  2. 在原生App\Http\Requests\Request的抽象扩展中使用MyCustomValidator

    abstract class MyCustomRequest extends Request {
    
        //Override native method by injecting the extending validator
        protected function formatErrors( MyCustomValidator $validator )
        {
            return $validator->getMessageBag()->toArray();
        }
    }
    
  3. 用具体类扩展MyCustomRequest

    class FooRequest extends MyCustomRequest
    {
    
        public function authorize()
        {
            return true;
        }
    
    
        public function rules()
        {
            return [
                // rules go here
            ];
        }
    }
    
  4. 在控制器方法中使用FooRequest

    public function store(FooRequest $request) {
        //use the request and persist
    }
    


我猜我缺少必需的外观、提供程序或容器绑定。我仍在学习这些主题,并且对它们的理解还不够好,无法知道下一步。

参考资料:

  • Custom validator in Laravel 5 - 我跟着答案,但仍然得到同样的错误。在排除我在这里尝试的问题之前,我想知道这是否与我的问题远程相关。

  • Extending Custom Validation-Class - 问题看起来很相似,答案建议使用Validator::extend,我知道可以在AppServiceProvider 中完成,但理想情况下我的代码应该在它自己的供应商包中。同样,不确定是否相关。

【问题讨论】:

    标签: php laravel-5 laravel-5.2 laravel-validation laravel-request


    【解决方案1】:

    我遇到了同样的问题,这就是我所做的。

    首先,创建一个类并将其命名为 CustomValidatorServiceProvider 或您想要的任何名称。在 CustomValidatorServiceProvider 中添加以下行。

    <?php
    
    namespace App\Providers;
    
    use Illuminate\Support\Facades\Event;
    use Illuminate\Validation\ValidationServiceProvider as ServiceProvider;
    use App\Services\Validator\Factory;
    
    class CustomValidatorServiceProvider extends ServiceProvider
    {
    
        /**
         * Register the validation factory.
         *
         * @return void
         */
        protected function registerValidationFactory()
        {
            $this->app->singleton('validator', function ($app) {
                $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['db']) && isset($app['validation.presence'])) {
                    $validator->setPresenceVerifier($app['validation.presence']);
                }
    
                return $validator;
            });
        }
    
    }
    

    如果您注意到我添加了自己的 Validator\Factory 并导入了它。 在 Validator\Factory 我有以下代码。

    <?php
    
    namespace App\Services\Validator;
    
    use Illuminate\Validation\Factory as ParentFactory;
    
    class Factory extends ParentFactory
    {
    
        /**
         * Resolve a new Validator instance.
         *
         * @param  array  $data
         * @param  array  $rules
         * @param  array  $messages
         * @param  array  $customAttributes
         * @return \Illuminate\Validation\Validator
         */
        protected function resolve(array $data, array $rules, array $messages, array $customAttributes)
        {
            if (is_null($this->resolver)) {
                return new Validator($this->translator, $data, $rules, $messages, $customAttributes);
            }
    
            return call_user_func($this->resolver, $this->translator, $data, $rules, $messages, $customAttributes);
        }
    }
    

    Validator\Factory 所在的同一目录中,我还添加了我的自定义 Validator Class,它将是扩展 Validator Class 的类> 框架。它包含以下代码。

    <?php
    
    namespace App\Services\Validator;
    
    use Illuminate\Validation\Validator as ParentValidator;
    use Illuminate\Support\Str;
    
    class Validator extends ParentValidator
    {
    
        /**
         * Replace all place-holders for the greater_than_equal rule.
         *
         * @param  string  $message
         * @param  string  $attribute
         * @param  string  $rule
         * @param  array   $parameters
         * @return string
         */
        protected function replaceGreaterThanEqual($message, $attribute, $rule, $parameters)
        {
            $replacers[0] = str_replace('_', ' ', Str::snake($parameters[0]));
            $replacers[1] = $attribute;
            return str_replace([':other', ':attribute'], $replacers, $message);
        }
    
        /**
         * Replace all place-holders for the after_or_equal rule.
         *
         * @param  string  $message
         * @param  string  $attribute
         * @param  string  $rule
         * @param  array   $parameters
         * @return string
         */
        protected function replaceAfterOrEqual($message, $attribute, $rule, $parameters)
        {
            return $this->replaceGreaterThanEqual($message, $attribute, $rule, $parameters);
        }
    }
    

    最后,我们应该在 providers 数组下添加我们在 config/app.php 中创建的 Service Provider

    App\Providers\CustomValidatorServiceProvider::class,
    

    您已经可以删除或注释掉 ValidationServiceProvider

    Illuminate\Validation\ValidationServiceProvider::class,
    

    【讨论】:

    • 这太接近解决我的问题了...但是如何在控制器中使用自定义验证器?
    【解决方案2】:

    例如,您可以通过以下方式将 validator 规则添加到您的 Request 类中:

    public function validator(\Illuminate\Contracts\Validation\Factory $factory)
    {
        $this->addExtraRules($factory);
    
        return $factory->make(
            $this->all(), $this->container->call([$this, 'rules']),
            $this->messages(), $this->attributes()
        );
    }
    

    现在你需要实现addExtraRules方法,例如:

    protected function addExtraRules(\Illuminate\Contracts\Validation\Factory $validator)
    {
        $validator->extendImplicit('equals_2',
            function ($attribute, $value, $parameters, $validator) {
               return $value == 2;
            });
    }
    

    关于此错误:App\Http\Requests\FooRequest,请确保您已在 FooRequest 类文件中以这种方式定义命名空间:

    namespace App\Http\Requests;
    

    【讨论】:

    • 我正在尝试覆盖 Validator::doReplacements 方法。已编辑问题以供澄清
    猜你喜欢
    • 1970-01-01
    • 2016-07-05
    • 2013-01-15
    • 2016-09-20
    • 2018-06-10
    • 2016-06-17
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    相关资源
    最近更新 更多