ZF2 remove isEmpty validation for form element - php

I need use form element with out isEmpty validation. This is my code.
$this->add(array(
'name' => 'test',
'type' => 'Zend\Form\Element\Number',
'attributes' => array(
'class' => 'form-control',
)
));
But following validation message is given.
[test] => Array
(
[isEmpty] => Value is required and can't be empty
)
How can i remove it?

Look here:
https://github.com/zendframework/zf2/blob/master/library/Zend/Form/Element/Number.php#L95
You can extend this class and overload getInputSpecification function and return array without 'required' => true
Like this:
namespace Your\Form\Elements;
use Zend\Form\Element\Number;
class NumberWithoutRequired extends Number{
public function getInputSpecification()
{
return array(
'name' => $this->getName(),
'required' => false,
'filters' => array(
array('name' => 'Zend\Filter\StringTrim')
),
'validators' => $this->getValidators(),
);
}
}
And then use this class for input in Your form instead of original Zend\Form\Element\Number class

If you have a specific form class, add a getInputFilterSpecification method with your validation rules:
class MyForm extends \Zend\Form\Form
{
public function init() // or __construct() if not using element manager
{
$this->add(array(
'name' => 'test',
'type' => 'Zend\Form\Element\Number',
'attributes' => array(
'class' => 'form-control',
)
));
}
public function getInputFilterSpecification()
{
return [
'test' => [
'required' => false,
]
];
}
}

You could do that by creating new ValidatorChain, and then loop through the validators attached to your element and dettach the Zend\Validator\NotEmpty validator. Just like this :
$newValidatorChain = new \Zend\Validator\ValidatorChain;
foreach ($form->getInputFilter()->get('test')->getValidatorChain()->getValidators()
as $validator)
{
//Attach all validators except the \Zend\Validator\NotEmpty one
if (!($validator['instance'] instanceof \Zend\Validator\NotEmpty)) {
$newValidatorChain->addValidator($validator['instance'],
$validator['breakChainOnFailure']);
}
}
$form->getInputFilter()->get('test')->setValidatorChain($newValidatorChain);

Related

How to call a controller function inside the form in zend 2

i am new in zend framework
i need to add dynamic values inside the form selection elements
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'SECTOR_ID',
'attributes' => array(
'class' => 'form-control select2drop',
'id' => 'Sector_ID'
),
'options' => array(
'value_options' => $this->getOptionsForSectorSelect(),
),
'disable_inarray_validator' => true
));
above code help me to get dynamic values
but i need to call a controller function for getting value , now i wrote getOptionsForSectorSelect inside the form
Please help me
You could make the method inside your Controller static
class IndexController extends AbstractActionController {
public static function getOptionsForSectorSelect() {
// Building dynamic array ...
return $dynamicArray;
}
// More code ...
}
Or you could pass the array with your form when creating it in your action like so:
public function indexAction() {
$dynamicArray = $this->getOptionsForSectorSelect();
$myForm = new YourForm($dynamicArray);
// more action code...
}
And then in your form:
class YourForm extends Form {
private $dynamicArray;
public function __construct(array $dynamicArray) {
$this->dynamicArray = $dynamicArray;
}
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'SECTOR_ID',
'attributes' => array(
'class' => 'form-control select2drop',
'id' => 'Sector_ID'
),
'options' => array(
'value_options' => $this->dynamicArray,
),
'disable_inarray_validator' => true,
));
}
Hope it helps! :)

ZF2 add elemets to form on the fly from database

In ZF2, I get the form from the controller factory like this:
class SomeControllerFactory implements FactoryInterface
{
public function CreateService(SeviceLocatorInterface $serviceLocator)
{
$realServiceLocator = $serviceLocator->getServiceLocator();
// other things from service manager
$registrationForm = $realServiceLocator->get('FormElementManager')
->get('Path\To\My\Form\RegistrationForm');
}
return new SomeController(
// controller dependencies, including $registrationForm
);
}
In the RegistrationForm, I have MultiCheckBox:
$this->add([
'type' => 'Zend\Form\Element\MultiCheckBox',
'name' => 'partyRoleIds',
'options' => [
'label' => 'Отношение',
'value_options' => [
[
'value' => '1',
'label' => 'client',
],
[
'value' => '2',
'label' => 'prospect'],
[
'value' => '6',
'label' => 'contractor',
],
],
],
]);
I want to populate value_options from a db query that returns an array like [1 => 'client', 2 => 'prospect'...]. Populating is not an problem, but I don't know how to pass this array as a dependency into the RegistrationForm because in the call $registrationForm = $realServiceLocator->get('FormElementManager')->get('Path\To\My\Form\RegistrationForm');, I don't have any place to add the dependency.
How could I do this?
PS: rewritten the question, please forgive my initial brevity.
In form classes you add the method :
public function setValueOptions($element, array $values_options)
{
$e = $this->get($element);
$e->setValueOptions($values_options);
return $this;
}
In your controller, if your form is $registrationForm you write :
$registrationForm->setValueOptions('partyRoleIds', $valueOptions);
where $valueOptions is an array like your sample.

How to get ZF2 fieldset validation working?

I have a simple form currently consisting of a single fieldset. Now I want the fields to be filtered and validated. So I implemented the method getInputFilterSpecification() in my Fieldset class:
...
class FooFieldset extends \Zend\Form\Fieldset
{
public function __construct($name = null, $options = array())
{
parent::__construct($name, $options);
$this->setHydrator(new ClassMethods(false));
$this->setObject(new Buz());
$this->setLabel('Baz');
$this->add(array(
'type' => 'text',
'name' => 'bar',
'options' => array(
'label' => _('bar')
)
));
}
public function getInputFilterSpecification()
{
return [
'bar' => [
'required' => true,
'filters' => [
0 => [
'name' => 'Zend\Filter\StringTrim',
'options' => []
]
],
'validators' => [],
'description' => _('bar lorem ipsum'),
'allow_empty' => false,
'continue_if_empty' => false
]
];
}
}
and added the Fieldset to the Form:
...
class BuzForm extends \Zend\Form\Form
{
public function __construct($name = null, $options = array())
{
parent::__construct($name, $options);
$this->setAttribute('role', 'form');
$this->add(array(
'name' => 'baz-fieldset',
'type' => 'Buz\Form\BazFieldset'
));
$this->add(array(
'type' => 'submit',
'name' => 'submit',
'attributes' => array(
'value' => 'preview'
)
));
}
}
The problem is, that the InputFilter specifications are completely ignored. I've set a breakpoint into FooFieldset#getInputFilterSpecification() and to be sure even checked it witha die() -- the method is not called.
What is wrong here and how to get it working correctly?
You will need to implement Zend\InputFilter\InputFilterProviderInterface interface in order for the getInputFilterSpecification() method to be called.

How to use collections in a fieldset factory in ZF2

I am developing a project with ZF2 and Doctrine. I am attempting to use Doctrine Hydrator in the form creation as shown in this tutorial. In this method, an ObjectManager object is created in the controller and passed to the new form when it is instantiated. Passing the ObjectManager object from the controller to the form creates a problem when I want to use ZF2's FormElementManager because ZF2 requires that I get an instance of the form class through the Zend\Form\FormElementManager instead of directly instantiating it. To work around this requirement, I have created form and fieldset factories based upon the answer to the question How to pass a Doctrine ObjectManager to a form through ZF2 FormElementManager. The method presented in the answer to the question works for typical fieldset elements, but I need to determine how to include a collection element. The tutorial uses the ObjectManager object in the collection element in the parent fieldset, and I need to figure out how to add the collection using a factory.
TagFieldset from the tutorial that I am trying to emulate:
namespace Application\Form;
use Application\Entity\Tag;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
class TagFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct('tag');
$this->setHydrator(new DoctrineHydrator($objectManager))
->setObject(new Tag());
$this->add(array(
'type' => 'Zend\Form\Element\Hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'name',
'options' => array(
'label' => 'Tag'
)
));
}
public function getInputFilterSpecification()
{
return array(
'id' => array(
'required' => false
),
'name' => array(
'required' => true
)
);
}
}
new TagFieldsetFactory:
namespace Application\Form;
use Zend\Form\Fieldset;
use Application\Entity\Tag;
class TagFieldsetFactory
{
public function __invoke($formElementManager, $name, $requestedName)
{
$serviceManager = $formElementManager->getServiceLocator();
$hydrator = $serviceManager->get('HydratorManager')->get('DoctrineEntityHydrator');
$fieldset = new Fieldset('tags');
$fieldset->setHydrator($hydrator);
$fieldset->setObject(new Tag);
//... add fieldset elements.
$fieldset->add(['...']);
//...
return $fieldset;
}
}
BlogPostFieldset from the tutorial that I am trying to emulate:
namespace Application\Form;
use Application\Entity\BlogPost;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
class BlogPostFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct('blog-post');
$this->setHydrator(new DoctrineHydrator($objectManager))
->setObject(new BlogPost());
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
$tagFieldset = new TagFieldset($objectManager);
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));
}
public function getInputFilterSpecification()
{
return array(
'title' => array(
'required' => true
),
);
}
}
new BlogPostFieldsetFactory:
namespace Application\Form;
use Zend\Form\Fieldset;
use Application\Entity\BlogPost;
class BlogPostFieldsetFactory
{
public function __invoke($formElementManager, $name, $requestedName)
{
$serviceManager = $formElementManager->getServiceLocator();
$hydrator = $serviceManager->get('HydratorManager')->get('DoctrineEntityHydrator');
$fieldset = new Fieldset('blog_post');
$fieldset->setHydrator($hydrator);
$fieldset->setObject(new BlogPost);
//... add fieldset elements.
$fieldset->add(['...']);
//...
return $fieldset;
}
}
in module.config.php:
'form_elements' => [
'factories' => [
'UpdateBlogPostForm' => 'Application\Form\UpdateBlogPostFormFactory',
'BlogPostFieldset' => 'Application\Form\BlogPostFieldsetFactory',
'TagFieldset' => 'Application\Form\TagFieldsetFactory',
],
],
When I add the fieldset elements In my new BlogPostFieldsetFactory I replace this code from the original fieldset:
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
with this:
$fieldset->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
How do I replace the collection element from the original fieldset:
$tagFieldset = new TagFieldset($objectManager);
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));
maybe i'm getting your question wrong.... but if you replaced this
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
whith this:
$fieldset->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
then you probably can replace this:
$tagFieldset = new TagFieldset($objectManager);
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));
with this:
$tagFieldset = new TagFieldset($objectManager);
$fieldset->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));
now, if you cant pass the $objectManger to the form... well if you look at the code you have this thing available $serviceManager, that thing looks like a DI container, im sure you can get the $objectManager instance from there, and if is not available, you can probably put an instance of it inside.
So de final code probably ending looks like this:
$objectManager = $serviceManager->get('DoctrineObjectManager') //or something like this
$tagFieldset = new TagFieldset($objectManager);
$fieldset->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));

Set validators in form ZendFramework2

I'm trying to write my first form in ZF2 and my code is
namespace Frontend\Forms;
use Zend\Form\Form;
use Zend\Validator;
class Pagecontent extends Form
{
public function __construct($name = null)
{
// we want to ignore the name passed
parent::__construct('logo');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'content_yes_no',
'type'=>'text',
'required' => true,
'validators' => array(
'name' => 'Alnum',
'options'=>array(
'allowWhiteSpace'=>true,
),
),
));
}
}
I want to know can I set validators like this?
Please advice
You've got to surround validators by another array:
'validators' => array(
array(
'name' => 'Alnum',
'options' => array(
'allowWhiteSpace'=>true,
),
),
),
To setup filters and validators you need an inputFilter. Typically you will find the inputFilter defined in the form class or associated model class. Here is a template for a form.
<?php
/* All bracket enclosed items are to be replaced with information from your
* implementation.
*/
namespace {Module}\Form;
class {Entity}Form
{
public function __construct()
{
// Name the form
parent::__construct('{entity}_form');
// Typically there is an id field on the form
$this->add(array(
'name' => 'id',
'type' => 'Hidden',
));
// Add a csrf field to help with security
$this->add(array(
'type' => 'Zend\Form\Element\Csrf',
'name' => 'csrf'
));
// Add more form fields here
$this->add(array(
'name' => 'example',
'type' => 'Text',
'options' => array(
'label' => 'Example',
),
));
//Of course we need a submit button
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Submit',
'id' => 'submitbutton',
),
));
}
}
The form defines all of the elements that will be displayed in the form. Now, you can either create the inputFilter in the form's class or in a model that is associated with the form's class. Either way it would look like:
<?php
/* All bracket enclosed items are to be replaced with information from your
* implementation.
*/
namespace {Module}\Model;
/*
* Include these if you require input filtering.
*/
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
class {Model} implements InputFilterAwareInterface
{
/*
* Add in model members as necessary
*/
public $id;
public $example;
/*
* Declare an inputFilter
*/
private $inputFilter;
/*
* You don't need a set function but the InputFilterAwareInterface makes
* you declare one
*/
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
/*
* Put all of your form's fields' filters and validators in here
*/
public function getInputFilter()
{
if (!$this->inputFilter)
{
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'id',
'required' => true,
'filters' => array(
array('name' => 'Int'),
),
)));
// This example input cannot have html tags in it, is trimmed, and
// must be 1-32 characters long
$inputFilter->add($factory->createInput(array(
'name' => 'example',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 32,
),
),
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
Then when you are programming your controller's action you can bring it all together like this:
if($request->isPost())
{
$model = new Model;
$form->setInputFilter($model->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid())
{
// Do some database stuff
}
}
Notice that we get the inputFilter from the model and use the form's setInputFilter() method to attach it.
To summarize, You must create a form class to place all of your form elements in, then create an inputFilter to hold all of your filters and validators. Then you can grab the inputFilter in the controller and apply it to the form. Of course this is just a couple ways to skin a cat though.
You can use Input Filter component:
<?php
namespace Frontend\Forms;
use Zend\Form\Form;
use Zend\Validator;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilter;
class Pagecontent extends Form
{
public function __construct($name = null)
{
...
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'content_yes_no',
'required' => true,
'filters' => array(),
'validators' => array(
array(
'name' => 'Alnum',
'options' => array(
'allowWhiteSpace' => true,
),
),
),
)));
$this->setInputFilter($inputFilter);
}
}
// your controller
$form = new \Frontend\Forms\Pagecontent();
$form->setData($request->getPost());
if ($form->isValid()) {
// your code
}

Categories