Проверка zf2: как проверить зависимые поля?

Как я могу установить входной фильтр, который зависит от другого поля ввода. Я хочу убедиться, что поле «apDepTime» больше, чем «apArrTime».

Как я могу справиться с этим в zf2?

Я также хочу отметить, что я использую «Проверку даты».

Пожалуйста, помогите мне кто-нибудь.

FlightDataForm.php

<?php

namespace FcFlight\Form;

use Zend\Form\Form;
use Zend\Form\Element;

class FlightDataForm extends Form
{
/**
 * @var string
 */
protected $_formName = 'flightData';

/**
 * @param null $name
 * @param array $options
 */
public function __construct($name = null)
{
    if (!is_null($name)) {
        $this->_formName = $name;
    }

    parent::__construct($this->_formName);

    //Fieldset Ap Dep
    $this->add(array(
        'name'          => 'apDep',
        'type'          => 'Zend\Form\Fieldset',
        'options'       => array(
            'legend'        => 'App Dep',
        ),
        'elements'      => array(
            array(
                'spec' => array(
                    'name' => 'apDepTime',
                    'type' => 'Zend\Form\Element\Text',
                    'attributes' => array(
                        'required' => true,
                        'maxlength' => '5',
                        'id' => 'apDepTime',
                    ),
                    'options' => array(
                        'label' => 'Time',
                        'hint' => 'HH:MM',
                        'description' => 'UTC',
                    ),
                ),
            ),
        ),
    ));

    //Fieldset Ap Arr
    $this->add(array(
        'name'          => 'apArr',
        'type'          => 'Zend\Form\Fieldset',
        'options'       => array(
            'legend'        => 'App Arr',
        ),
        'elements'      => array(
            //apArrTime
            array(
                'spec' => array(
                    'name' => 'apArrTime',
                    'type' => 'Zend\Form\Element\Text',
                    'attributes' => array(
                        'required' => true,
                        'maxlength' => '5',
                        'id' => 'apArrTime',
                    ),
                    'options' => array(
                        'label' => 'Time',
                        'hint' => 'HH:MM',
                        'description' => 'UTC',
                    ),
                ),
            ),
        ),
    ));

    $this->add(new Element\Csrf('csrf'));

    //Submit button
    $this->add(array(
        'name' => 'submitBtn',
        'attributes' => array(
            'type' => 'submit',
            'value' => 'Add',
        ),
    ));

}
}

FlightDataFilter.php

<?php
namespace FcFlight\Filter;

use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\Db\Adapter\Adapter;

class FlightDataFilter implements InputFilterAwareInterface
{

/**
 * @var $inputFilter
 */
protected $inputFilter;

/**
 * @var $dbAdapter
 */
protected $dbAdapter;

/**
 * @var string
 */
protected $table = '';

public $apDepTime;
public $apArrTime;

/**
 * @param \Zend\Db\Adapter\Adapter $dbAdapter
 */
public function __construct(Adapter $dbAdapter)
{
    $this->dbAdapter = $dbAdapter;
}

/**
 * @return \Zend\Db\Adapter\Adapter
 */
public function getDbAdapter()
{
    return $this->dbAdapter;
}

/**
 * Array to Object
 *
 * @param array $data
 */
public function exchangeArray(array $data)
{
    $this->apDepTime = (isset($data['apDep']['apDepTime'])) ? $data['apDep']['apDepTime'] : null;
    $this->apArrTime = (isset($data['apArr']['apArrTime'])) ? $data['apArr']['apArrTime'] : null;
}

/**
 * @return array
 */
public function getArrayCopy()
{
    return get_object_vars($this);
}

/**
 * @param InputFilterInterface $inputFilter
 * @return void|InputFilterAwareInterface
 * @throws \Exception
 */
public function setInputFilter(InputFilterInterface $inputFilter)
{
    throw new \Exception("Not used");
}


/**
 * @return \Zend\InputFilter\InputFilter|\Zend\InputFilter\InputFilterInterface
 */
public function getInputFilter()
{
    if (!$this->inputFilter) {

        $inputFilter = new InputFilter();
        $factory = new InputFactory();

        $flightNumberInputFilter = new InputFilter();

        $flightNumberInputFilter->add($factory->createInput(array(
            'name' => 'flightNumberIdIcao',
            'required' => true,
        )));

        $apDepInputFilter = new InputFilter();

        $apDepInputFilter->add($factory->createInput(array(
            'name' => 'apDepTime',
            'required' => true,
            'validators' => array(
                array(
                    'name' => 'Date',
                    'options' => array(
                        'format' => 'H:i',
                    ),
                ),
            ),
        )));

        $inputFilter->add($apDepInputFilter, 'apDep');

        $apArrInputFilter = new InputFilter();

        $apArrInputFilter->add($factory->createInput(array(
            'name' => 'apArrTime',
            'required' => true,
            'validators' => array(
                array(
                    'name' => 'Date',
                    'options' => array(
                        'format' => 'H:i',
                    ),
                ),
                array(
                    'name' => 'Callback',
                    'options' => array(
                        'messages' => array(
                            \Zend\Validator\Callback::INVALID_VALUE => 'The arrival time is less than the departure time',
                        ),
                        'callback' => function($value, $context = array()) {
                            // value of this input
                            $apArrTime = \DateTime::createFromFormat('H:i', $value);
                            // value of input to check against from context
                            $apDepTime = \DateTime::createFromFormat('H:i', $context['apDepTime']);
                            // compare times, eg..
                            return $apDepTime > $apArrTime;
                        },
                    ),
                ),
            ),
        )));

        $inputFilter->add($apArrInputFilter, 'apArr');

        $this->inputFilter = $inputFilter;
    }

    return $this->inputFilter;
}
}

person Ruslan P    schedule 08.07.2013    source источник


Ответы (2)


Вы можете использовать валидатор Zend\Validator\Callback для этого

Первый параметр, передаваемый вашему обратному вызову, — это значение ввода, к которому применяется валидатор.

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

Как простой пример...

    $apArrInputFilter->add($factory->createInput(array(
        'name' => 'apArrTime',
        'required' => true,
        'validators' => array(
                array(
                    'name' => 'Callback',
                    'options' => array(
                        'messages' => array(
                            \Zend\Validator\Callback::INVALID_VALUE => 'The departure time is less than the arrival time',
                        ),
                        'callback' => function($value, $context=array()) {
                            // value of this input
                            $apArrTime = $value;
                            // value of input to check against from context
                            $apDepTime = $context['apDepTime'];
                            // compare times, eg..
                            $isValid = $apDepTime > $apArrTime;
                            return $isValid;
                        },
                    ),
                ),
        ),
    )));

Очевидно, вам нужно будет написать код, соответствующий вашим потребностям, для фактического сравнения дат, но это должно помочь вам начать работу.

person Crisp    schedule 08.07.2013
comment
Хрустящий. Спасибо большое. Я новичок в ЗФ. Ваше решение мне очень помогло. Но мой код не видит $context['apDepTime'], потому что apDepTime находится в другом InputFilter ($apDepInputFilter), и я не вижу $this в анонимной функции. - person Ruslan P; 09.07.2013
comment
Я обновил свой код, используя ваше решение. Осталось подумать, как получить значение apDepTime. - person Ruslan P; 09.07.2013

Вы также можете использовать другой подход. Используйте InputFilter для определения собственной функции isValid().

Скажите вашей форме использовать InputFilter.

$this->setInputFilter(new Filter\MyFilter());

Реализуйте свою собственную функцию isValid().

namespace Application\Form\Filter;

use Zend\InputFilter\InputFilter;  
use Zend\Validator;  
use Zend\Filter;

class MyFilter extends InputFilter  
{
    public function isValid($context = null)
    {
        // add your dependent validation 
    }

    public function __construct()
    {
        // Add youre form field validations
    }

http://theabstract.de/zf2-dynamic-form-validation/

person Stillmatic1985    schedule 14.04.2016