4

I read this question on SO: "how to disable inArray validator forms in zend framework2" and was trying to find it out, but couldn't find any way to detach/remove the InArray Validator. But InArray is just a validator. So how can remove a validator from the validator list of a form element?

I can get the validators:

$myElement = $form->getInputFilter()->get('city');
$validatorChain = $cityElement->getValidatorChain();
$validators = $validatorChain->getValidators();

and maybe can then unset the array element with the validator, I want to remove, and then pass the result array back to the Input object and to the form element. But it's really dirty and surely not the recommended way.

So how to remove a validator from a form element?

Community
  • 1
  • 1
automatix
  • 14,018
  • 26
  • 105
  • 230
  • 1
    did you try $inputFilter = new InputFilter(); $inputFilter->remove($name); And do you use **$factory = new InputFactory();** for example? – Remi Thomas Apr 27 '13 at 13:47
  • Thank you! Yes, it works: `$formInputFilter = $form->getInputFilter(); $formInputFilter->remove('city'); $formInputFilter->add((new Zend\InputFilter\Factory())->createInput(array( 'name' => 'city', 'required' => true, )));` But then I would have to create an `Input` in a view script. Dirty. – automatix Apr 27 '13 at 14:22
  • In your view just do $newInputFilter = new InputFilter(); //.. your stuff.. $inputFilter = new InputFilter(); $inputFilter->add($newInputFilter, "yourElement"); $form->setInputFilter($inputFilter); But it will be better in your controller! – Remi Thomas Apr 27 '13 at 14:32
  • The controller is also not an appropriate place for such form specific stuff. So, maybe somewhere in a Form Element View Helper. But anyway, the thing that really disturbs me is, that I have to define my Filters twice -- in `ModuleName\Model\FooInput` and somewhere else. And even if I can do it once, but not at the place, where all the other Inputs are defined centrally, it's not so clean, since it makes the code confusing. There should be a method at the form `Element` or at the `Input` object, that provides removing of validators. – automatix Apr 27 '13 at 14:46
  • I agree with you. maybe you can just add some conditions in your inputFilter (in constructor) to process some add or remove actions to your filters. Like this class YourInputFilter extends InputFilter { public function __construct($cityRequired = false) { //... blabla $formInputFilter->add((new Zend\InputFilter\Factory())->createInput(array( 'name' => 'city', 'required' => $cityRequired, ))); // or if($cityRequired){ // this validator }else{ // another validator } } } – Remi Thomas Apr 27 '13 at 14:58
  • 1
    Yes, the only clean(-er) way seems to extend the `InputFilter`, and/or `Input` class, and maybe also the `Element`. – automatix Apr 27 '13 at 15:15
  • 1
    See http://stackoverflow.com/questions/15782107/zend-framework-2-removed-form-element-causes-validation-to-fail – Sam Apr 27 '13 at 15:22
  • The only, clean way is to create a new FilterChain and copy over all the validators you want to keep. Then set the chain into the input filter for this particular element. Indeed, don't do that in your view, but there are other places where this might perfectly makes sense. – Jurian Sluiman Apr 28 '13 at 11:45

2 Answers2

6

Well, you could just replace the validator chain with a new one. Let's say I have an element with two validators:

  • Zend\Validator\NotEmpty
  • Zend\Validator\EmailAddress

And I want to remove the EmailAddress validator from it. You could do something like this:

// create new validator chain
$newValidatorChain = new \Zend\Validator\ValidatorChain;
// loop through all validators of the validator chained currently attached to the element
foreach ($form->getInputFilter()->get('myElement')->getValidatorChain()->getValidators() as $validator) {
    // attach validator unless it's instance of Zend\Validator\EmailAddress
    if (!($validator['instance'] instanceof \Zend\Validator\EmailAddress)) {
        $newValidatorChain->addValidator($validator['instance'], $validator['breakChainOnFailure']);
    }
}
// replace the old validator chain on the element
$form->getInputFilter()->get('myElement')->setValidatorChain($newValidatorChain);

Easy ;)

Richard Knop
  • 81,041
  • 149
  • 392
  • 552
  • Let me try, if this works it will be great help as at the moment "disable_inarray_validator" is only disabling the error message and nothing else w.r.t validation. – noobie-php Jul 08 '13 at 13:29
  • Thx for your effort,mate it worked for the moment but after i created new Validator chain, i later inspected it like this print_r($Form->getInputFilter()->get('account')->getValidatorChain()->getValidators());. And what i got in the end was an empty array(); now i was wondering if this algo removes all the validators in the chain. – noobie-php Jul 08 '13 at 14:41
  • This is the dump for ValidatorChain. Zend\Validator\ValidatorChain Object ( [plugins:protected] => [validators:protected] => Array ( ) [messages:protected] => Array ( ) ) – noobie-php Jul 08 '13 at 14:44
  • As of Zend 2.1 (I believe) addValidator() is deprecated and attach() should be used instead. Just leaving this here for future reference. – Adrian Aug 26 '13 at 20:41
3

I found this to work with 1.12.3

in my update form

$element = new My_Form_Element_Username('username');
$element->setValue('some-value');
$element->removeValidator('Db_NoRecordExists');
$this->addElement($element);

or

$this->addElement(new My_Form_Element_Username('username')
  ->setValue('some-value')
  ->removeValidator('Db_NoRecordExists');

My_Form_Element_Username just extends some Zend_Form_Element and has the validators defined.

Jaime
  • 31
  • 1