Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

zf2 validation: How can I validate dependent fields?

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;
}
}
like image 577
Ruslan P Avatar asked Jul 08 '13 15:07

Ruslan P


1 Answers

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.

like image 104
Crisp Avatar answered Oct 21 '22 07:10

Crisp