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() {}
}
ZF2 input validator for required not empty only when not null
Yes, you ought to use NotEmpty validator.
$inputFilter = new \Zend\InputFilter\InputFilter ();
$inputFilter->add ([
'name' => 'foo',
'validators' => [
[
'name' => 'not_empty',
'options' => [
'type' => 'string'
]
]
]
]);
$form->setInputFilter ($inputFilter);
Zend framework - how to allow empty field for form element
$freetext = $this->CreateElement('textarea', 'freetext')
->addValidator('StringLength', false, array(10,500))
->setRequired(false);
Your code should already do that, the setRequired(false)
method do what you're asking for, i.e. if the value is not submitted then validators won't be run.
Do you have any issue with the code you've written, some validation error messages or something else?
Update
I've changed the setRequired() to true - I want to allow empty string as an acceptable value on a require field.
What is the semantic in setRequired(true)
and allowing the empty string as a valid value? Or better what do you require if the element can be empty?
What you've asked in the edit is a no sense, because if an element is required it MUST have a value different from the empty string. If you need to accept the empty string as a valid value just use setRequired(false)
. When you get form values with Zend_Form::getValues()
or Zend_Form_Element::getValue()
you'll obtain the empty string as result.
Anyway here it's the explanation of setRequired
and setAllowEmpty
from ZF manual:
Using the defaults, validating an Element without passing a value, or
passing an empty string for it, skips all validators and validates to
TRUE.
setAllowEmpty(false) leaving the two other mentioned flags
untouched, will validate against the validator chain you defined for
this Element, regardless of the value passed to isValid().setRequired(true) leaving the two other mentioned flags untouched,
will add a 'NotEmpty' validator on top of the validator chain (if none
was already set)), with the $breakChainOnFailure flag set. This
behavior lends required flag semantic meaning: if no value is passed,
we immediately invalidate the submission and notify the user, and
prevent other validators from running on what we already know is
invalid data.
If you do not want this behavior, you can turn it off by passing a
FALSE value to setAutoInsertNotEmptyValidator($flag); this will
prevent isValid() from placing the 'NotEmpty' validator in the
validator chain.
ZF2 - Validator chain not running on empty elements
After a whole day of looking into this, I've found a route around the problem.
First off, the Zend\InputFilter\BaseInputFilter class contains the following for isValid():
public function isValid()
{
if (null === $this->data) {
throw new Exception\RuntimeException(sprintf(
'%s: no data present to validate!',
__METHOD__
));
}
$this->validInputs = array();
$this->invalidInputs = array();
$valid = true;
$inputs = $this->validationGroup ?: array_keys($this->inputs);
foreach ($inputs as $name) {
$input = $this->inputs[$name];
if (!array_key_exists($name, $this->data)
|| (null === $this->data[$name])
|| (is_string($this->data[$name]) && strlen($this->data[$name]) === 0)
) {
if ($input instanceof InputInterface) {
// - test if input is required
if (!$input->isRequired()) {
$this->validInputs[$name] = $input;
continue;
}
// - test if input allows empty
if ($input->allowEmpty()) {
$this->validInputs[$name] = $input;
continue;
}
}
// make sure we have a value (empty) for validation
$this->data[$name] = '';
}
if ($input instanceof InputFilterInterface) {
if (!$input->isValid()) {
$this->invalidInputs[$name] = $input;
$valid = false;
continue;
}
$this->validInputs[$name] = $input;
continue;
}
if ($input instanceof InputInterface) {
if (!$input->isValid($this->data)) {
// Validation failure
$this->invalidInputs[$name] = $input;
$valid = false;
if ($input->breakOnFailure()) {
return false;
}
continue;
}
$this->validInputs[$name] = $input;
continue;
}
}
return $valid;
}
As allowEmpty was true for my Input, the validation for that Input stops and moves on to the next Input element in the array. Changing allowEmpty to false on my Input solves that issue, but creates another, as the 'Zend\InputFilter\Input' class calls the following function during it's isValid() function:
protected function injectNotEmptyValidator()
{
if ((!$this->isRequired() && $this->allowEmpty()) || $this->notEmptyValidator) {
return;
}
$chain = $this->getValidatorChain();
// Check if NotEmpty validator is already first in chain
$validators = $chain->getValidators();
if (isset($validators[0]['instance'])
&& $validators[0]['instance'] instanceof NotEmpty
) {
$this->notEmptyValidator = true;
return;
}
$chain->prependByName('NotEmpty', array(), true);
$this->notEmptyValidator = true;
}
Because my field is required and allowEmpty is now false, a 'NotEmpty' validator is added to my chain automatically. Once that was discovered, the solution was simple. I created an 'Input' class in my custom library, which overrides the injectNotEmptyValidator function, forcing it to do nothing:
namespace Si\InputFilter;
class Input extends \Zend\InputFilter\Input {
protected function injectNotEmptyValidator() {
return;
}
}
Doing the above menas that 'NotEmpty' is NOT added to my validator chain, so my XOR validator can run correctly. All I have to do now is use my corrected Si\InputFilter\Input class to populate InputFilter for those two elements.
Hope that helps.
Zend Framework notEmpty validator setRequired
I agree that this is a little confusing. The reason is that all form elements have an allowEmpty
flag (true by default), that skips validation if the value is blank. It works this way because otherwise, adding validators to optional elements would be a real pain, e.g.:
$dateOfBirth = new Zend_Form_Element_Text('dob');
$dateOfBirth->setLabel('Date of birth (optional)');
$dateOfBirth->addValidator(new Zend_Validate_Date());
$form->addElement($dateOfBirth);
this would always fail validation if the user chose not to enter their DOB, as '' is not a valid date. With the allowEmpty
flag on by default it works as you would expect (it only validates the date when one has been entered).
Calling setRequired(true)
adds a NotEmpty
validator but it also sets the allowEmpty
flag to false. I would recommend you stick with this approach. Alternatively you can get your way to work by setting the flag as well:
$username = new Zend_Form_Element_Text('txtUsername');
$username->addValidator(new Zend_Validate_NotEmpty());
$username->setAllowEmpty(false);
Validator not working in Zend Framework 2
I think you missed something in the documentation tutorial. Your code is wrong.
You have :
'validators' => array(
array('name' => 'StringLength',
'encoding' => 'UTF-8',
'min' => 5,
'max' => 35
)
)
You should have this :
'validators' => array (
array (
'name' => 'StringLength',
'options' => array (//<-----options array here
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100
)
)
)
The min
, max
and encoding
should be in the options
array.
Conditionally required in Zend Framework's 2 InputFilter
First of all, you may want to enable validation on empty/null values as of Empty values passed to Zend framework 2 validators
You can use a callback input filter as in following example:
$filter = new \Zend\InputFilter\InputFilter();
$type = new \Zend\InputFilter\Input('type');
$smth = new \Zend\InputFilter\Input('smth');
$smth
->getValidatorChain()
->attach(new \Zend\Validator\NotEmpty(\Zend\Validator\NotEmpty::NULL))
->attach(new \Zend\Validator\Callback(function ($value) use ($type) {
return $value || (1 != $type->getValue());
}));
$filter->add($type);
$filter->add($smth);
This will basically work when the value smth
is an empty string and the value for type
is not 1
. If the value for type
is 1
, then smth
has to be different from an empty string.
Related Topics
How to Detect and Handle MySQL Warnings with PHP
Simple Form Not Sending Data via _Post
PHP Regex to Remove Http:// from String
Permission Denied Despite Appropriate Permissions Using PHP
Jetbrains Webide: PHP Variable Type Hinting
Nohup:Ignoring Input and Appending Output to 'Nohup.Out'
How to Validate on Max File Size in Laravel
How to Properly Display Chinese Characters in PHP
Preparing PHP Application to Use with Utf-8
Checking for Empty Arrays: Count VS Empty
Check If a Remote Page Exists Using PHP
Jquery Tablesorter Index Column Insert
How to Format Numbers to Have Only Two Decimal Places
Memory Optimization in PHP Array
How to Block Uploads of Nude Images