Как проверить поле Zend_Form на основе значения другого поля?

Я пытаюсь добавить пользовательский валидатор в поле. Он должен учитывать значение другого поля. Например. поле A должно быть не более B+50%.

Я создал класс, реализующий Zend_Validate_Interface, но, видимо, Zend Form отправляет валидатору только значение текущего поля. Как заставить валидатор получать все?


person Fluffy    schedule 28.09.2011    source источник


Ответы (1)


Когда вы вызываете isValid для Zend_Form, он передает все данные, которые вы передали методу

$form->isValid(array('a' => 1, 'b' => 2));

Ваш пользовательский валидатор получит весь этот массив необработанных значений.

Пример проверки

class My_Validator_TwoVals implements Zend_Validate_Interface
{
    public function getMessages()
    {
        return array();
    }
    public function isValid($value)
    {
        print_r(func_get_args());
    }
}

Пример формы

$f = new Zend_Form;
$a = $f->createElement('Text', 'a');
$b = $f->createElement('Text', 'b');
$b->addPrefixPath('My_Validator', '.', 'validate');
$b->addValidator('TwoVals');
$f->addElements(array($a, $b));

$f->isValid(array('a' => 1, 'b' => 2));

Вывод

Array
(
    [0] => 2
    [1] => Array
        (
            [a] => 1
            [b] => 2
        )
)

Как видите, в isValid также был передан второй аргумент — $context. И это содержит оставшиеся значения.

Альтернативой может быть передача второго элемента для сопоставления в качестве опции валидатору, например.

class My_Validator_TwoVals implements Zend_Validate_Interface
{
    protected $a;
    public function getMessages()
    {
        return array();
    }
    public function isValid($value)
    {
        var_dump($this->a->getValue());
    }
    public function __construct(Zend_Form_Element $a)
    {
        $this->a = $a;
    }
}

Настройка

$f = new Zend_Form;
$a = $f->createElement('Text', 'a');
$b = $f->createElement('Text', 'b');
$b->addPrefixPath('My_Validator', '.', 'validate');
$b->addValidator('TwoVals', false, array($a));
$f->addElements(array($a, $b));

$f->isValid(array('a' => 1, 'b' => 2));

Затем напечатает int(1). Как видите, мы получили это значение через API элемента формы, поэтому все, что вы настроили для валидаторов и фильтров, будет применено, например. это не исходное значение. И вы также можете установить для него другое значение и т. д.

Также взгляните на Zend_Validate_Identical, чтобы узнать, как ZF реализует проверку других элементов формы:

person Gordon    schedule 28.09.2011
comment
Ну, я думаю, вы ошиблись с первой частью. Вы звоните isValid $b вместо $f. Я проверил это перед публикацией, и вызов isValid в форме не отправляет все данные элементу isValid. Читаю дальше ответ - он немаленький) - person Fluffy; 28.09.2011
comment
@Пушистый мой плохой, извини. Тем не менее, это правильно. Смотрите мое обновление. Полный массив будет в $context. - person Gordon; 28.09.2011
comment
На самом деле ты прав. Не знаю, почему об этом нет упоминания в документации Zend_Validate_Interface. Спасибо, кажется, это то, что я искал - person Fluffy; 28.09.2011
comment
@Fluffy Я полагаю, это потому, что это нарушит обратную совместимость, если они изменят подпись isValid на интерфейсе. Все валидаторы, реализующие это, должны будут изменить свои методы, чтобы включить $context, а затем соответствовать определению интерфейса. - person Gordon; 28.09.2011