zf2 validation: How can I validate dependent fields?
validation, zend-framework2
Solution
You can use the `Zend\Validator\Callback` validator for this
The first parameter passed to your callback is the value of the input to which the validator is applied.
The second parameter is an array of your other form values keyed by input names and represents the context in which you want to compare values.
As a simple example...
$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;
},
),
),
),
)));
Obviously you'll need to write code to your needs for the actual date comparison, but that should get you started.
Problem
How can I set a input filter which is dependent from another input field. I want to verify that the 'apDepTime' field is more than 'apArrTime'. How can i handle this in zf2? I also want to note that I am using 'Date validator'. Please help me anybody. 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; } } ```