代码之家  ›  专栏  ›  技术社区  ›  erenon

zend_形式任意数量的键值对字段

  •  1
  • erenon  · 技术社区  · 15 年前

    我正在尝试使用Zend_窗体(Zend_框架组件)创建窗体。用户应该能够添加任意数量的字段。就像你可以用Gmail图形用户界面上传文件一样。 例子:

    [_____] [+]
    

    单击[+]按钮后:

    [_____]
    [_____] [+]
    

    为了使事情复杂化,我想添加字段 ,所以看起来是这样的:

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

    如何在实现此功能的同时保持轻松的内置验证和分配方法的可用性?我需要子窗体吗?我还需要别的吗?提交表单后,代码应该能够将字段映射到和数组中。

    恐怕我必须将zend_form或subform分为子类,但我想知道最简单/最漂亮的方法。

    3 回复  |  直到 14 年前
        1
  •  1
  •   nwhiting    15 年前

    这里最简单的方法是使用一个简单的自定义Zend验证器,当整个数组php看到输入元素时,它将解析输入元素,这样您就能够自动执行以下操作。

    1. 独立验证每个输入元素,并显示与每个元素关联的错误消息。
    2. 返回一个可分析的数组以重建刚提交的表单。

    对于Zend_验证器

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

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

        2
  •  0
  •   Derek Illchuk    15 年前

    下面是如何添加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. 查看另一个隐藏变量以了解要显示的字段总数——甚至是那些空字段。
    3. 等。
        3
  •  0
  •   erenon    14 年前

    以下是我自己的解决方案: 我创建了两个隐藏字段,一个用于键,一个用于值。一段javascript代码在deamnd上创建了假字段对,一旦更改,它就会使用json将所有假字段映射到隐藏字段中。 在服务器端很容易处理,但使用的javascript技术并不离散。