I wonder if I'm doing something wrong or if this is a bug in ZF2: When i'm trying to set some data on a form, validate it and retrieve the data it's just an empty array.
I extracted this code from some classes to simplify the problem
$form = new \Zend\Form\Form;
$form->setInputFilter(new \Zend\InputFilter\InputFilter);
$form->add(array(
'name' => 'username',
'attributes' => array(
'type' => 'text',
'label' => 'Username',
),
));
$form->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Register',
),
));
if ($this->getRequest()->isPost()) {
$form->setData($this->getRequest()->getPost()->toArray());
if ($form->isValid()) {
echo '<pre>';
print_r($form->getData());
print_r($form->getMessages());
echo '</pre>';
}
}
both print_r()s show empty arrays. I don't get any Data out of the form as well as no messages. Is it my fault or ZF2's?
Thanks to #SamuelHerzog and #Sam,
the form needs inputFilters for all elements. In the case of the form described in the question this short code is enough to get it work at all.
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'username'
)));
$form->setInputFilter($inputFilter);
It's not required to have any rules for the element, it just needs to be added to the inpoutFilter to work basically. By default any element has the required flag and must not be a blank value.
Related
I have a form in my ZF2 app with a CAPTCHA element as follows :
$this->add(array(
'type' => 'Zend\Form\Element\Captcha',
'name' => 'captcha',
'attributes' => array(
'class'=>'form-control',
),
'options' => array(
'label' => 'Please verify you are human.',
'captcha' => array('class' => 'Dumb')
),
));
I have an input filter attached to the form that validates the other elements in the form (name, email, message). When this is attached to the form the validation for the CAPTCHA field is ignored when checking if valid.
if ($request->isPost()) {
// set the filter
$form->setInputFilter($form->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) { ...
If i remove the input filter then the CAPTCHA field is validated correctly but obviously the other fields have no validators. What silly mistake am I making? Is there a "CAPTCHA" validator I have to set in the input filter?
The issue is because, I assume that on your form you have created a method called:
getInputFilter();
which overrides the original getInputFilter(),
there are two solutions:
rename your function on your form to be getInputFilterCustom()
and then modify also:
if ($request->isPost()) {
// set the filter
$form->setInputFilter($form->getInputFilterCustom());
or inside your current getInputFilter() add the logic to validate the captcha.
This is my code to add a captcha image control in a ZF2 form :
$this->add(array(
'name' => 'captcha',
'type' => 'Captcha',
'attributes' => array(
'id' => 'captcha',
'autocomplete' => 'off',
'required' => 'required'
),
'options' => array(
'label' => 'Captcha :',
'captcha' => new \Zend\Captcha\Image(array(
'font' => 'public/fonts/arial.ttf',
'imgDir' => 'public/img/captcha',
'imgUrl' => 'img/captcha'
))
),
));
The others form elements are using validators from the input filter, but i didn't use any validators to make it work.
I hope this can help you.
It is because you don't call the parent getInputFilter() within yours. Simply do
public function getInputFilter()
{
parent::getInputFilter();
//... your filters here
}
I am facing an error to edit the values of my Entity Category. Here is my code
Bearbeiten
In my IndexController is the Action:
public function editAction()
{
$id = (int) $this->params()->fromRoute('id');
$em = $this->getEntityManager();
$category = $em->getRepository('Application\Entity\Category')->find($id);
$form = new CategoryForm();
$form->setHydrator(new CategoryHydrator());
$form->bind($category);
$request = $this->getRequest();
if($request->isPost())
{
$form->setData($this->getRequest()->getPost());
if($form->isValid())
{
$object = $form->getData();
$category->setName($object->getName());
$category->setDescription($object->getDescription());
$category->setParent($object->getParent());
$em->flush();
return $this->redirect()->toRoute('home');
}
}
return array(
'form' => $form
);
}
Here is my CategoryForm.php:
namespace Application\Form;
use Zend\Form\Form;
class CategoryForm extends Form
{
public function __construct()
{
parent::__construct('categoryForm');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'name',
'attributes' => array(
'type' => 'text',
'id' => 'name',
),
'options' => array(
'label' => 'Ihr Name:',
),
));
$this->add(array(
'name' => 'description',
'attributes' => array(
'type' => 'text',
'id' => 'description',
),
'options' => array(
'label' => 'Ihre Beschreibung:',
),
));
$this->add(array(
'name' => 'parent',
'attributes' => array(
'id' => 'parent',
'name' => 'parent',
'type' => 'hidden',
),
));
$this->add(array(
'name'=>'submit',
'attributes'=>array(
'type' => 'submit',
'value' => 'OK',
),
));
}
}
And the following is my edit.phtml:
<?php
$form = $this->form;
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formRow($form->get('name'));
echo $this->formRow($form->get('description'));
echo $this->formRow($form->get('parent'));
echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag();
?>
By calling the action 'edit', the browser shows a error with the message:
Object provided to Escape helper, but flags do not allow recursion
Does someone knows my mistake and can help me?
First, from your question it can only be quessed what the $child->getId() is. I assume the $child is an instance of the Category class, and getId() returns an integer, being the category's id. So instead, i just put this, for testing, in my index.phtml:
Bearbeiten
To be on the safe side, I have also passed an instance of Category to index.phtml as $child variable, used your code for the link, and the link worked, (so it's not something wrong with url view helper). Anyway, I could just write the url into the browser and click enter, but since I don't know where your error showed up, (perhaps after clicking the link), I had to make sure :)
Next, I copied your code exactly, except for this line:
$form->setHydrator(new CategoryHydrator());
You did not provide the code for your hydrator. I assume you've created it, but without it being shown to me, I can only assume there is an error somewhere in the hydrator code. Instead of that line, try:
$form->setHydrator ( new \DoctrineModule\Stdlib\Hydrator\DoctrineObject ( $em, 'Application\Entity\Category' ) );
I hope I can safely assume that DoctrineModule was installed with composer and is added to your 'modules' array in application.config.php.
With this line, otherwise the code being exactly as yours, after a click on the link, or entering the URI /application/edit/1 ( 1 being the id of my category to edit), the form was displayed and the input fields were populated correctly, without any errors.
If there's still something wrong, perhaps there is some error in your Category entity.
This might be a bit strange, but I'll try to explain. Basically I have a table containing users and a table containing customers. Users have permission to look into the data of only certain customers. So I figured I would make a separate table for user permissions, taking the user ID and the customer ID as foreign keys and having one row per customer/user permission.
When the admin adds a new user to the database using a class called UserForm (posted shortened below for reference), which uses Zend\Form, I want to also display all the customers next to the form as buttons that can be selected to be added as permissions. Now, I thought I would do that by having a JavaScript array that appends or removes the customer IDs if they're selected/deselected, then passing that array to the form as a hidden value and finally looping through the array inserting a row into the permissions table for each customer ID in the array, and taking the user ID that's been created as well. I'm not sure if this is the best way to do it, but it's the best I could come up with.
Hope that's at least slightly understandable. So, I have one form, but I want to insert into two different tables. My question, I guess, is how do I pass the array to the form as a value? And how do I insert into not only the users table, but also the permissions table, when the saveUser() method is called (I'll post that below too). Also, is this a really weird way of doing it that I'm being unnecessarily difficult about? I'd love to hear if there's a much easier way.
My UserForm class:
namespace Admin\Form;
use Zend\Form\Form;
class UserForm extends Form
{
public function __construct($name = null)
{
parent::__construct('user');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'userId',
'attributes' => array(
'type' => 'Hidden',
),
));
$this->add(array(
'name' => 'activated',
'attributes' => array(
'value' => 1,
'type' => 'Hidden',
),
));
$this->add(array(
'name' => 'username',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Username:',
),
));
$this->add(array(
'name' => 'firstname',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'First name:',
),
));
$this->add(array(
'name' => 'lastname',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Last name:',
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
}
My saveUser() method
public function saveUser(User $user)
{
$data = array(
'firstname' => $user->firstname,
'lastname' => $user->lastname,
'username' => $user->username,
'activated' => $user->activated,
);
$userId = (int)$user->userId;
if ($userId == 0) {
$this->tableGateway->insert($data);
} else {
if ($this->getUser($userId)) {
$this->tableGateway->update($data, array('userId' => $userId));
} else {
throw new \Exception('User ID does not exist');
}
}
}
One method is to use Form Fieldsets. A form can have multiple Fieldsets, and each Fieldset can be bound to a different entity.
These are useful when you have a one to one relationship between the entities
You would then create teo entities, for example a User entity (as you already have) and a new entity to represent your Permission.
You would create a Feildset for each and bind the objects to the fields sets. (UserFieldSet and PermissionFieldset for example)
checkout the section on Form Fieldsets:
http://zf2.readthedocs.org/en/latest/modules/zend.form.advanced-use-of-forms.html
If you have a one to many relationship, ie. One User can have Many Permissions, then you would be better off looking at form Collections:
http://zf2.readthedocs.org/en/latest/modules/zend.form.collections.html
there's an example of dynamically adding new rows for a one to many relationship too.
I'm trying to build a VERY simple form and want to add the validation in the form itself. No need for million lines of code when adding it in the form just is about 3 lines.
Here are two of my fields:
$this->add(array(
'name' => 'username',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Name*',
'required' => true,
),
'filters' => array(
array('StringTrim')
),
));
$this->add(array(
'name' => 'email',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'E-Mail*',
'required' => true,
),
'validators' => array(
array('regex', true, array(
'pattern' => '/[A-Z0-9._%-]+#[A-Z0-9.-]+\.[A-Z]{2,4}/i',
'messages' => 'Bitte eine gültige E-Mailadresse angeben'))
),
'filters' => array(
array('StringTrim')
),
));
The $form->isValid() ALWAYS returns true. Even if the field is empty. I have another field with a regex-validator, same thing... WTF, Zend?
My controller looks like this:
$form = new UserForm();
$form->setHydrator(new DoctrineEntity($entityManager));
$request = $this->getRequest();
if ($request->isPost()) {
$backenduser = new User();
$form->bind($user);
$form->setData($request->getPost());
if ($form->isValid()) {
....
}
Any ideas?
Validation- and Filtering-Definitions aren't part of the Form itself. See http://framework.zend.com/manual/2.0/en/user-guide/forms-and-actions.html
Try this, pass $_POST data.
if($form->isValid($_POST)) {
// success!
} else {
// failure!
}
I am trying to have a form with float number validation.
when validation works it won't let me click the submit button and will show the proper error message.
I am using zend framework 2 and in my Form I want to retrieve alcohol volume.
I'm trying to use the following code:
$this->add($factory->createElement(array(
'name' => 'alcohol_vol',
'attributes' => array(
'label' => 'alcohol vol%:',
'filters' => array('Float'),
'type' => 'text',
'required' => true,
),
)));
this doesn't do anything actually. it will pass validation if i enter regular text.
I also tried changing the type to 'Number' from 'text' but then it won't allow me to use floating number. it will allow only none-float numbers :)
There is no "Float" filter in ZF2, I guess may you want is "Float" Validator, Float Validator could be add into ZF2 form like this:
$this->add($factory->createElement(array(
'name' => 'alcohol_vol',
'attributes' => array(
'label' => 'alcohol vol%:',
'type' => 'text',
),
)));
$factory = new Zend\InputFilter\Factory();
$this->setInputFilter($factory->createInputFilter(array(
'alcohol_vol' => array(
'name' => 'alcohol_vol',
'required' => true,
'validators' => array(
array(
'name' => 'Float',
),
),
),
)));
Then you should validate form in controller, above validators should still set into form. If input not float, the input element will have invalidate messages:
$form->setData($userInputData);
if (!$form->isValid()) {
$inputFilter = $form->getInputFilter();
$invalids = $inputFilter->getInvalidInput();
var_dump($invalids);
// output: 'abc' does not appear to be a float
}
I think you can use this filter
new Zend\I18n\Filter\NumberFormat("en_US", NumberFormatter::TYPE_DOUBLE);
I recommend the Zend\I18n\Validator\Float class. Example usage:
$floatInput = new Input('myFloatField');
$floatInput->getValidatorChain()
->attach(new \Zend\I18n\Validator\Float());
See:
http://framework.zend.com/manual/2.3/en/modules/zend.input-filter.intro.html
http://framework.zend.com/manual/2.0/en/modules/zend.validator.set.html#validating-digits