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