ZF2: 'required' => false ignored for DateSelect element - zend-framework2

In a Zend Framework 2 application, I have the following form in my controller action method:
public function testAction()
{
$form = new \Zend\Form\Form('test');
$date = new \Zend\Form\Element\DateSelect('date');
$date->setOptions(array(
'label' => 'Date',
'min_year' => date('Y') - 10,
'max_year' => date('Y') + 10,
)
);
$date->getDayElement()->setEmptyOption('day');
$date->getMonthElement()->setEmptyOption('month');
$date->getYearElement()->setEmptyOption('year');
$form->add($date);
$form->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'submit',
'id' => 'submitbutton',
),
));
if ($this->request->isPost()) {
$data = $this->request->getPost();
$form->setData($data);
if ($form->isValid()) {
$data = $form->getData();
// more code
}
}
return array('form' => $form);
}
Now if I submit the form I get the validation message:
'The input does not appear to be a valid date'
That is correct but I would only want to know if the field is required. If I look in the source of the DateSelect element, I see a getInputSpecification() method that sets required to false by default and there also is a getValidator() method requiring a format with which the empty date does not comply.
How can I bypass validation if the input is not required (obviously, in my real form I have more elements)?

I usually use the factory pattern and you can set whether the field is required ie
$inputFilter->add($factory->createInput(array(
'name' => 'availableDate',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'max' => 20,
),
),
),
)));
refer the field required - you can set this to false

Related

Get an input validator from a form object in zf2

I have the following input filter:
'term' => array(
'required' => false,
'filters' => array(
array(
'name' => 'StringTrim',
)
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'max' => 128
)
)
)
),
I need to get programmatically from a form object the value of the 'max' option inside the 'validators' property.
$vc = $form->getInputFilter()->get('term')->getValidatorChain()->getValidators();
foreach($vc as $v){
if($v['instance'] instanceof \Zend\Validator\StringLength)
$max = $v['instance']->getMax();
}

Zend Framework 2 inputfilter incorrect behaviour

there is a more than strange behavior of filterInput, the getting filter function itself is:
public function getInputFilter($id = null){
if (!$this->inputFilter){
$inputFilter = new InputFilter();
$factory = new InputFactory();
$id = intval($id);
$inputFilter->add($factory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'field' => 'name',
'table' => 'table',
'adapter' => $this->dbAdapter,
'message' => 'record exists',
'exclude' => array(
'field' => 'id',
'value' => $id
)
),
)
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
setting the filter like:
$form->setInputFilter($model->getInputFilter($id));
Now, when we fire $form->isValid(), the validation error will rise about duplication in the database, if I will remove Db\NoRecordExists validator, the database will contain 2 records! more interesting, if I will set 'required' => false, there will be no double inserting, the same with adding second validation field. Working settings are:
public function getInputFilter($id = null){
if (!$this->inputFilter){
$inputFilter = new InputFilter();
$factory = new InputFactory();
$id = intval($id);
$inputFilter->add($factory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'field' => 'name',
'table' => 'table',
'adapter' => $this->dbAdapter,
'message' => 'record exists',
'exclude' => array(
'field' => 'id',
'value' => $id
)
),
)
),
)));
//test field
$inputFilter->add($factory->createInput(array(
'name' => 'id',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
array('name' => 'Int')
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
So it fails to work correctly with filter config for only one field.. Does anybody knows the reason?

In Zend Framework 2, how do you change the message in the DateStep validator

In \Zend\Validator\DateStep, I want to override the error message shown below:
protected $messageTemplates = array(
self::NOT_STEP => "The input is not a valid step"
);
I have an input filter connected to a form containing an element of the type 'Zend\Form\Element\Date' which automatically calls the DateStep validator.
Here is the relevant part of my form:
$this->add(array(
'type' => 'Zend\Form\Element\Date',
'name' => 'appointment-date',
'options' => array(
'label' => 'Appointment Date',
'format' => 'Y-m-d'
),
'attributes' => array(
'min' => date('Y-m-d'), // today's date
'max' => '2020-01-01',
'step' => '2', // days; default step interval is 1 day
)
));
Here is my input filter:
$inputFilter->add($factory->createInput(array(
'name' => 'appointment-date',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
),
'validators' => array(
array(
'name' => 'DateStep',
'options' => array(
//'step' => new DateInterval("P2D"),
//'baseValue' => new DateTime(),
'messages' => array(
\Zend\Validator\DateStep::NOT_STEP => 'Must be a day in the future',
),
),
),
),
)));
The inputFilter seems to be ignored. I tried setting up the step and baseValue in the inputFilter, but that seems to not work at all. Working app can be found here: https://github.com/bickerstoff/zf2_datetest if more details are needed.
Looks like you're trying to filter a "Date" input with a "DateStep" validator.
$this->add(array(
'type' => 'Zend\Form\Element\Date',
'name' => 'appointment-date',
'options' => array(
'label' => 'Appointment Date',
'format' => 'Y-m-d'
),
'attributes' => array(
'min' => date('Y-m-d'), // today's date
'max' => '2020-01-01',
'step' => '2', // days; default step interval is 1 day
)
));
This may cause your problem.

ZF2 Dynamic Form Filters/Validators

I'm setting up a controller that will create a form.
I can't use an extended to Form class, so i need to build up my form on my controller.
$form = new Form('example');
$fieldset = new Fieldset('default');
$fieldset->add(array('name' => 'example_field', 'attributes' => array('type' => 'text', 'id' => 'example_field'), 'options' => array('label' => 'Example Field',),));
$form->add($fieldset);
The main question here is, how do I define the filters and validators for each element/fieldset without required to create a class implementing InputFilterAwareInterface, so i can do everything from my controller?
Thanks in advance!
You could add/remove form Validators by handle InputFilter of form, here is my example:
$form = new \Zend\Form\Form();
$name = array(
'name' => 'username',
'options' => array(
'label' => 'Your name',
),
'attributes' => array(
'type' => 'text'
),
);
$form->add($name);
$filter = $form->getInputFilter();
$filter->remove('username');
$filter->add(array(
'name' => 'username',
'required' => true,
'validators' => array (
'stringLength' => array (
'name' => 'StringLength',
'options' => array (
'max' => '3',
),
),
),
));
$form->setInputFilter($filter);
$form->setData(array(
'username' => 'longtext',
));
$form->prepare();
echo $form->isValid(); //false
print_r($form->getMessages()); //stringLengthTooLong error will show
Add validator dynamically:
$form->getInputFilter()->get('element_name')->getValidatorChain()->attach(new ValidatorClassName());
Add filter dynamically:
$form->getInputFilter()->get('element_name')->getFilterChain()->attach(new FilterClassName());

zendframework 2 inputfilter customize default error message

I am trying to customize the default error message "Value is required and can't be empty"
in zf2
I am using following code to add customise default error message in validators of inputfilter
$inputFilter->add($factory->createInput(array(
'name' => 'username',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 4,
'max' => 20,
'messages' => array(
'isEmpty' => 'Please enter User Name between 4 to 20 character!'
),
),
),
),
)));
But I am getting following error.
Zend\Validator\Exception\InvalidArgumentException
File:
/home/website/vendor/zendframework/zendframework/library/Zend/Validator/AbstractValidator.php:220
Message:
No message template exists for key 'isEmpty'
What I am doing wrong?
reference
try this
$inputFilter->add($factory->createInput(array(
'name' => 'username',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' =>'NotEmpty',
'options' => array(
'messages' => array(
\Zend\Validator\NotEmpty::IS_EMPTY => 'Please enter User Name!'
),
),
),
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 4,
'max' => 20,
'messages' => array(
'stringLengthTooShort' => 'Please enter User Name between 4 to 20 character!',
'stringLengthTooLong' => 'Please enter User Name between 4 to 20 character!'
),
),
),
),
)));
reference
Other validator set
You also can set the error message of inputFilter so:
$form = new ParticipantForm();
$mailInput = new Input('mail');
$mailInput->setRequired(true);
$mailInput->setErrorMessage("Empty input");
The StringLength validator does not check for the input to be empty or not. It checks against lengths. Following message templates exist for StringLength validator:
const INVALID = 'stringLengthInvalid';
const TOO_SHORT = 'stringLengthTooShort';
const TOO_LONG = 'stringLengthTooLong';
/**
* #var array
*/
protected $messageTemplates = array(
self::INVALID => "Invalid type given. String expected",
self::TOO_SHORT => "The input is less than %min% characters long",
self::TOO_LONG => "The input is more than %max% characters long",
);
See the example of #Developer for a direct approach. Though i suggest going with the CamelCased naming of the Validators, so 'name' => 'NotEmpty' instead of 'name' => 'not_empty'
You can check which messageTemplates exist if you see the code for each of the validator classes. You will find them under ./vendor/zendframework/zendframework/library/Zend/Validator/*

Resources