web-dev-qa-db-ja.com

Zend Framework2バリデーターに渡される空の値

Zend Framework 2 ValidatorChainを介して空の値をカスタムバリデーターに渡すにはどうすればよいですか?

ZF1ではallowEmpty(false)によって可能でした

要素値が空のZF2の場合:

  • allowEmpty = falseの場合、NotEmptyValidatorがValidatorChainの先頭にbreakOnFailure = true@see Zend/InputFilter/Input#injectNotEmptyValidatorで追加されます。

  • allowEmpty = trueの場合、要素は有効と見なされます、@see Zend/InputFilter/BaseInputFilter#isValid

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

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バリデーターを独自にアタッチし、setRequiredおよびsetAllowEmptyへの呼び出しを回避することです。これは基本的に 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() {}
}
14
Ocramius

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;
    }

    // ...
}
26
anilyeni

これにより、値が空の文字列の場合に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はその後に続くバリデーターによる評価を許可します。

7
Onshop

InputFilter構成配列でallowEmptyを使用して間違いを犯している人をよく見かけます。文字列は、キャメルケースではなく、アンダースコアで区切って書く必要があります。そう allow_empty 動作します:

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

つまり、キー 'fieldName'のフィールドがデータに存在する必要がありますが、その値は空にすることができます。

2
Wilt

別のフォーム検証クラスまたは配列表記を検証に使用する場合は、次のように実行できます。

$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 => falseおよびallowEmpty => trueを含む配列を入力フィルターファクトリに渡すことができます(入力フィルターにも直接渡すことができることを覚えていますが、よくわかりません)。

2
Ruwantha