多次扩展Laravel验证器

时间:2014-03-21 21:32:34

标签: php validation laravel package

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

文档说要扩展Validator,然后使用Validator::resolver注册新的扩展类。这样可以正常工作,但仅限于单个解析器,因为似乎每个后续定义的解析器都会覆盖前一个解析器。

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

由于

//

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

2 个答案:

答案 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\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 of Illuminate \ Validation \ ValidationServiceProvider`。

立面Validator现在指向MyValidator。您甚至可以创建多个工厂,向MyValidationServiceProvider添加(和调用)方法以注册其他验证器类,以将新工厂映射到新的IoC绑定,创建新的外观类,并向外墙添加条目在app.php中为每个验证器设置不同的外观。