ZF: Form array field - how to display values in the view correctly

Posted by Wojciech Fracz on Stack Overflow See other posts from Stack Overflow or by Wojciech Fracz
Published on 2012-10-31T11:42:35Z Indexed on 2013/11/03 9:54 UTC
Read the original article Hit count: 210

Filed under:
|

Let's say I have a Zend_Form form that has a few text fields, e.g:

$form = new Zend_Form();
$form->addElement('text', 'name', array(
    'required' => true,
    'isArray' => true,
    'filters' => array( /* ... */ ),
    'validators' => array( /* ... */ ),
));
$form->addElement('text', 'surname', array(
    'required' => true,
    'isArray' => true,
    'filters' => array( /* ... */ ),
    'validators' => array( /* ... */ ),
));

After rendering it I have following HTML markup (simplified):

<div id="people">
    <div class="person">
        <input type="text" name="name[]" />
        <input type="text" name="surname[]" />
    </div>
</div>

Now I want to have the ability to add as many people as I want. I create a "+" button that in Javascript appends next div.person to the container. Before I submit the form, I have for example 5 names and 5 surnames, posted to the server as arrays. Everything is fine unless somebody puts the value in the field that does not validate. Then the whole form validation fails and when I want to display the form again (with errors) I see the PHP Warning:

htmlspecialchars() expects parameter 1 to be string, array given

Which is more or less described in ticket: http://framework.zend.com/issues/browse/ZF-8112

However, I came up with a not-very-elegant solution. What I wanted to achieve:

  • have all fields and values rendered again in the view
  • have error messages only next to the fields that contained bad values

Here is my solution (view script):

<div id="people">
<?php
$names = $form->name->getValue(); // will have an array here if the form were submitted
$surnames= $form->surname->getValue();

// only if the form were submitted we need to validate fields' values
// and display errors next to them; otherwise when user enter the page
// and render the form for the first time - he would see Required validator
// errors
$needsValidation = is_array($names) || is_array($surnames);

// print empty fields when the form is displayed the first time
if(!is_array($names))$names= array('');
if(!is_array($surnames))$surnames= array('');

// display all fields!
foreach($names as $index => $name):
    $surname = $surnames[$index];
    // validate value if needed
    if($needsValidation){
        $form->name->isValid($name);
        $form->surname->isValid($surname);
    }
?>
  <div class="person">
     <?=$form->name->setValue($name); // display field with error if did not pass the validation ?>
     <?=$form->surname->setValue($surname);?>
  </div>
<?php endforeach; ?>
</div>

The code work, but I want to know if there is an appropriate, more comfortable way to do this? I often hit this problem when there is a need for a more dynamic - multivalue forms and have not find better solution for a long time.

© Stack Overflow or respective owner

Related posts about zend-framework

Related posts about zend-form