How to make this filter run after this Validator

I have an element. I want to add a special validator and a custom filter to it. The validator ensures that the input is one of several valid values, then the filter adds some custom values ​​to the input. This means that before starting the filter, I have to check the original input. I do it in this order

$element = new Zend_Form_Element_Text('element'); $element->addValidator('PermittedValue', false); $element->addFilter('TotalHyphen', false); $this->addElement($element); 

but this order is not respected. The filter starts first and changes the data, then the validator works with the filtered data, which means that it always fails even for valid input. It appears from the documentation that this is intentional

Note. Validation works with the Values ​​filter. Zend_Form_Element :: isValid () filters the values ​​through the provided filter chain before validation. See the "Filters" section for more info.

How to specify the execution order of validators and filters?

+6
php zend-framework zend-validate zend-filter
source share
4 answers

Of course, it seems that creating a custom element that supports filtering after validation will be a way. How about this:

 /** * An element that supports post-validation filtering */ class My_Form_Element_PostValidateFilterable extends Zend_Form_Element_Text { protected $_postValidateFilters = array(); public function setPostValidateFilters(array $filters) { $this->_postValidateFilters = $filters; return $this; } public function getPostValidateFilters() { return $this->_postValidateFilters; } public function isValid($value, $context = null) { $isValid = parent::isValid($value, $context); if ($isValid){ foreach ($this->getPostValidateFilters() as $filter){ $value = $filter->filter($value); } $this->setValue($value); } return $isValid; } } 

Usage will be something like this:

 $elt = $form->addElement('PostValidateFilterable', 'myElement', array( 'label' => 'MyLabel', 'filters' => array( 'StringTrim', // etc ), 'validators' => array( 'NotEmpty', // etc ), // here comes the good stuff 'postValidateFilters' => array( new My_Filter_RunAfterValidateOne(), new My_Filter_RunAfterValidateTwo(), ), )); 

This keeps correctness and filtering in shape - a thin controller.

Not verified, just a blow in the dark. And, of course, you could adjust / change the API to add / remove filters with a key, etc.

What do you think?

+7
source share

Perhaps do not add a filter at all. First check the contents in the controller, and then use the filter separately:

 $request = $this->getRequest(); if ($request->isPost() && $form->isValid($request->getParams())) { $filter = new Filter_Whatever(); $val = $filter->filter($request->getParam('element')); ... //call your model or whatever } 

I have never done this, but I believe that this (or something similar) may work.

+4
source share

Good idea!,

AFAIK filters should or should be performed before checking input: from ZF docs

It is often useful and / or necessary to do some normalization at the input before validation. For example, you might want to delete all HTML files, but check your checks for what remains to ensure that the view is valid. Or you can trim the empty space surrounding the input, so the StringLength Installer will use the correct input length without counting leading or trailing whitespace.

but if and only if you are in a case that mingos cannot solve, the answer should be help

+1
source share

What you want to achieve is to change the default behavior of how the text element is processed. That way, I think you could create your own element (e.g. My_Form_Element_Text) that extends Zend_Form_Element_Text and overloads its isValid () method.

In particular, you can simply change the second line in the original isValid () method, from $value = $this->getValue(); up to $value = $this->getUnfilteredValue(); . This way your check will be done using unfiltered values.

+1
source share

All Articles