Zend Framework 2 - Removed Form Element Causes Validation to Fail

Zend Framework 2 - Removed form element causes validation to fail

Ok, finally I found a solution! You can define a ValidationGroup which allows you to set the attributes you'd like to validate. The others are not validated:

$form->setValidationGroup('name', 'email', 'subject', 'message');
$form->setData($data);
if ($form->isValid()) {
...

Strange form validation behavior in Zend Framework 2

Many people loathed the forms in ZF1.x for the decorators but I loved it nonetheless. What is the worst part for me with ZF2 is that you can basically throw out all your knowledge because like so many things in ZF2 it has completely changed.

There is the new (HTML5) email element but it comes with a hard coded required constraint. Similar stuff happens with select elements. In ZF1 you had the setRequired() method on the element but it is now moved back into what are "inputs" in the form. In other word you have to get the inputs first.

$form->prepare();  // this is another new thing and necessary

$input = $form->getInputFilter();
$e_filter = $input->get('email');
$e_filter->setRequired(false);

$g_filter = $input->get('gender');
$g_filter->setRequired(false);

Now your form should accept empty submissions.

UPDATE: As for the postback problem.
It all depends on the data you set with setData(). This could be either the POST data or on a redirect data from a session. If you submit without a selection the POST data you get should not have any "gender" data and so should the data you set into the form.

UPDATE 2
It looks like the root problem is that an empty gender value is submitted and POST values are always strings, hence an empty value is of type string with length 0. Looking into Form\View\Helper\FormSelect and the rendering of the option you will find a in_array($value, $selectedOptions) function handling the selected attribute. Unfortunately they don't set the strict flag and without that a 0 (zero) value matches an empty string.

$post = array('gender' => '');
$bool = in_array(0, $post); // this is true
$bool = in_array(0, $post, true); // but this is false

So, either filter/remove this empty value from the POST or change the empty string to NULL before you'll add it to setData() then it will be droped as a selected option. Additionally if you can of course add/change the strict option in the Zend class (which I wouldn't do).

How to disable/remove a validator of a element depending on the value of another element?

I've got around the problem by overwriting the isValid() method in the form:

class CreateProduct extends Form
{
public function init()
{
/* ... */
}

public function isValid()
{
if (!$this->get('product')->get('isSale')->isChecked()) {
$this->getInputFilter()->get('product')->remove('salePrice');
$this->get('product')->get('salePrice')->setValue(null);
}
return parent::isValid();
}
}

It feels so hacky though!

Zend framework 2 optional form validation

To set the validator in an input filter you would do something like this in a validator class:

$inputFilter->add($factory->createInput(array(
'name' => 'foo_bar_input',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim')
),

// add your validators here
'validators' => array(
// check to see if an input is empty
array(
'name' => 'Zend\Validator\NotEmpty',
'options' => array(),
)
)
)));

Then to use the filter with your form, do something like:

$validate = $this->getServiceLocator()->get('your_validator_class');
$form->setInputFilter($validate->getInputFilter());

The just check to see if your form is valid:

if ($form->isValid()) 
{
// do stuff
}

Here is ZF2's documentation on the NotEmpty validator:
http://framework.zend.com/manual/2.0/en/modules/zend.validator.set.html#notempty

Set Zend Framework 2 form element to disabled

Simply use disabled attribute instead of setting element options:

$dropDownForCheckBox->setAttribute('disabled', 'disabled');

Empty values passed to Zend framework 2 validators

Following works for ZF2 version 2.1.1:

The problem (if I got it correctly) is that in following example, for empty values of 'fieldName', no validation is triggered. This can be quite annoying, though in

$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

This is quite annoying when you have particular cases, like checking an URL assigned to a page in your CMS and avoiding collisions (empty URL is still an URL!).

There's a way of handling this for empty strings, which is to basically attach the NotEmpty validator on your own, and avoiding calls to setRequired and setAllowEmpty. This will basically tell Zend\InputFilter\Input#injectNotEmptyValidator not to utomatically attach a NotEmpty validator on its own:

$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)

If you also want to check against null, you will need to extend Zend\InputFilter\Input as following:

class MyInput extends \Zend\InputFilter\Input
{
// disabling auto-injection of the `NotEmpty` validator
protected function injectNotEmptyValidator() {}
}


Related Topics



Leave a reply



Submit