The easiest approach to take here is to use a simple custom Zend Validator, that would parse input elements as the entire array PHP see it as so you are able to perform the following automatically.
- Validate each input element independently and display the error messages associated for each element.
- Return a parse-able array to rebuilt the form that was just submitted.
For the Zend_Validator
class Validate_InputArray extends Zend_Validate_Abstract
{
const INVALID = 'invalid';
const ERROR = 'error';
/**
* Failed array elements used to regenerate same elements
* on next form build
*
*/
protected $_elements = array();
protected $_messageTemplates = array(
self::INVALID => "Could not locate post element %value%",
self::ERROR => "YOUR ERROR MESSAGE|%value% is required"
);
public function __construct()
{}
public function isValid($element)
{
if (!$_POST[$element]) {
$this->_error(self::INVALID);
return false;
}
$elements = array();
if (is_array($_POST[$element])) {
$fail = false;
foreach ($_POST[$element] as $k => $v) {
if (!$this->_validateElement($v)) {
$this->_error(self::ERROR);
$elements[$k] = self::ERROR;
}
}
$this->_setElements($elements);
if ($fail) {
return false;
}
} else {
if (!$this->_validateElement($_POST[$element])) {
$this->_error(self::ERROR);
$elements[0] = self::ERROR;
$this->_setElements($elements);
return false;
}
}
}
protected function _setElements($elements)
{
$this->_elements = $elements;
return $this;
}
public function getElements()
{
return $this->_elements;
}
private function _validateElement($value)
{
// do your validation here
// return true/false
}
}
Now the code using this to parse an input with a possible array as an a value and validate each element and regenerate the exact form submitted, with the identical arbitrary fields.
$fail = false;
if ($this->getRequest()->isPost()) {
require 'Validate_InputArray.php';
$validator = new Validate_InputArray();
$elements = array();
if (!$validator->isValid($validator)) {
$fail = true;
foreach ($validator->getElements() as $k => $v) {
$elements[$k] = $v;
}
}
}
if ($fail) {
$messages = $validator->getMessages();
foreach ($elements as $k => $v) {
// Add custom methods here
$element = $form->createElement('text', 'elementName[]');
$element->addErrorMessages($messages[$k]);
}
} else {
$form->addElement('elementName[]');
}
This will allow you to validate any number of arbitrary input elements as needed without the need to sub-form, or worry about the need to re-add the form elements if and when a arbitrary element fails validation and needs to be rebuilt on the client side.