Zend_Form任意数量的键值对字段

时间:2009-12-22 15:47:54

标签: php zend-framework zend-form

我正在尝试使用Zend_Form(Zend_Framework组件)创建表单。用户应该能够添加任意数量的字段。正如您可以使用gmail GUI上传文件一样。 例如:

[_____] [+]

点击[+]按钮后:

[_____]
[_____] [+]

为了让事情变得复杂,我想添加字段,所以它看起来像这样:

[_____] [_____]
[_____] [_____] [+]

在实现此功能时,如何保持简单内置验证的可用性并分配方法?我需要一个子表单吗?我需要别的东西吗?提交表单后,代码应该能够将字段映射到数组。

我担心我必须继承Zend_Form或SubForm,但我想知道最简单/最漂亮的方式。

3 个答案:

答案 0 :(得分:1)

最简单的方法是使用一个简单的自定义Zend Validator,它将输入元素解析为PHP看到的整个数组,因此您可以自动执行以下操作。

  1. 独立验证每个输入元素,并显示与每个元素关联的错误消息。
  2. 返回一个可解析的数组,以重建刚刚提交的表单。
  3. 对于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
     }
    }
    

    现在使用此代码解析输入,使用可能的数组作为值并验证每个元素并重新生成提交的确切表单,并使用相同的任意字段。

    $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[]');
    }
    

    这将允许您根据需要验证任意数量的任意输入元素,而无需子表单,或者担心在任意元素验证失败并需要重建时需要重新添加表单元素在客户端。

答案 1 :(得分:0)

以下是如何添加10个输入字段,每个字段都有Alpha验证:

$sub_test = new Zend_Form_SubForm();
$num_fields = 10;
for ( $i = 0; $i < $num_fields; $i++ ) {
  $element = $form->createElement('text', strval($i));
  $element->addValidator('Alpha'); // just to see in action
  $sub_test->addElement($element);
}
$form->addSubForm($sub_test, 'test'); // values mapped to $_POST['test'][0..9]

要确定创建/展示的数量,当然,您需要做更多的工作,但这似乎很简单。

  1. 查看$ _POST ['test']以查看填写了多少值 - 始终包含这些值。
  2. 查看另一个隐藏变量,了解要显示的总字段数 - 即使是空字段。

答案 2 :(得分:0)

这是我自己的解决方案: 我创建了两个隐藏字段,一个用于键,一个用于值。一段javascript代码在deamand上创建伪字段对,而onChange,它使用JSON将所有伪字段映射到隐藏字段。 它很容易在服务器端处理,但使用的javascript技术不是离散的。