传递给Zend框架2验证器的空值


Empty values passed to Zend framework 2 validators

如何通过Zend framework 2 ValidatorChain将空值传递给我的自定义验证器?

allowEmpty(false) 在ZF1上是可能的

在ZF2上,元素值为空:

  • 如果是allowEmpty = false,则NotEmptyValidator与breakOnFailure = true@see Zend/InputFilter/Input#injectNotEmptyValidator一起添加到ValidatorChain的顶部。

  • 如果allowEmpty = true,则元素被视为有效,@see Zend/InputFilter/BaseInputFilter#isValid

    if ($input->allowEmpty()) {
        $this->validInputs[$name] = $input;
        continue;
    }
    

continue_if_empty解决了我的问题。感谢@dson horácio junior。这就是我使用的:

$this->add(array(
    'name' => 'field',
    'continue_if_empty' => true,
    'filters' => array(
        array('name' => 'StripTags'),
        array('name' => 'StringTrim')
    ),
    'validators' => array(
        array(
            'name' => 'Application'Form'Validator'Sample'
        )
    )
));
public function isValid($value, $context = null)
{
    if ($value == '' && $context['otherfield'] == '') {
        $this->error(self::INVALID_FIELD);
        return false;
    }
    // ...
}

ZF2 2.1.1版的以下工作:

问题是(如果我正确的话)在下面的例子中,对于'fieldName'的空值,不会触发验证。这可能很烦人,尽管在中

$input = new 'Zend'InputFilter'Input('fieldName');
$input
    ->setAllowEmpty(true)
    ->setRequired(false)
    ->getValidatorChain()
    ->attach(new 'Zend'Validator'Callback(function ($value) {
        echo 'called validator!';
        return true; // valid
    }));
$inputFilter = new 'Zend'InputFilter'InputFilter();
$inputFilter->add($input);
$inputFilter->setData(array('fieldName' => 'value'));
var_dump($inputFilter->isValid()); // true, echoes 'called validator!'
$inputFilter->setData(array('fieldName' => ''));
var_dump($inputFilter->isValid()); // true, no output
$inputFilter->setData(array());
var_dump($inputFilter->isValid()); // true, no output

当你遇到特殊情况时,这很烦人,比如在CMS中检查分配给页面的URL并避免冲突(空URL仍然是URL!)。

对于空字符串,有一种处理方法,那就是基本上自己附加NotEmpty验证器,并避免调用setRequiredsetAllowEmpty。这基本上会告诉Zend'InputFilter'Input#injectNotEmptyValidator不要自动附加NotEmpty验证器:

$input = new 'Zend'InputFilter'Input('fieldName');
$input
    ->getValidatorChain()
    ->attach(new 'Zend'Validator'NotEmpty('Zend'Validator'NotEmpty::NULL))
    ->attach(new 'Zend'Validator'Callback(function ($value) {
        echo 'called validator!';
        return true; // valid
    }));
$inputFilter = new 'Zend'InputFilter'InputFilter();
$inputFilter->add($input);
$inputFilter->setData(array('fieldName' => 'value'));
var_dump($inputFilter->isValid()); // true, echoes 'called validator!'
$inputFilter->setData(array('fieldName' => ''));
var_dump($inputFilter->isValid()); // true, echoes 'called validator!'
$inputFilter->setData(array());
var_dump($inputFilter->isValid()); // false (null was passed to the validator)

如果您还想对照null进行检查,则需要按照以下方式扩展Zend'InputFilter'Input

class MyInput extends 'Zend'InputFilter'Input
{
    // disabling auto-injection of the `NotEmpty` validator
    protected function injectNotEmptyValidator() {}
}

当值为空字符串时,这触发了对我的Callback验证器的验证:

'required'          => false,
'allow_empty'       => false,
'continue_if_empty' => true,
'validators'        => array(
    array(
        'name'    => 'Callback',
        'options' => array(
            'callback' => function ($value, $context = []) use ($self) {
                // ...
            }
        )
    )
)

allow_empty最初使空字符串无效,continue_if_empty允许随后的验证器对其进行评估。

我经常看到有人在inputFilter配置数组中使用allowEmpty犯错误。字符串应该用下划线分隔而不是用驼色大小写。因此allow_empty将起作用:

'fieldName' => array(
    'name'        => 'fieldName',
    'required'    => true,
    'allow_empty' => true,
    'filters' => array(
        //... your filters ...
    )
    'validators' => array(
        //... your validators ...
    ),
);

这意味着数据中必须存在关键字为"fieldName"的字段,但允许其值为空。

如果您喜欢使用单独的表单验证类或数组表示法进行验证,可以执行以下操作:

$factory     = new Zend'InputFilter'Factory();
$inputFilter = new Zend'InputFilter'InputFilter();
$inputFilter->add($factory->createInput(array(
    'name' => 'name',
    'required' => false,
    'allowEmpty' => true,
    'filters' => array(
        array('name' => 'StripTags'),
        array('name' => 'StringTrim'),
    ),
    'validators' => array(
        array(
            'name' => 'StringLength',
            'options' => array(
                'encoding' => 'UTF-8',
                'min' => '8',
                'max' => '100',
            ),
        ),
    ),
)));

您可以将一个带有required => falseallowEmpty => true的数组传递给输入过滤器工厂(我记得您也可以直接将其传递给输入滤波器——不太确定)。