Zend_Form произвольное количество полей пары ключ-значение - PullRequest
1 голос
/ 22 декабря 2009

Я пытаюсь создать форму, используя Zend_Form (компонент Zend_Framework). Пользователи должны иметь возможность добавлять произвольное количество полей. Так же, как вы можете загружать файлы с помощью gmail GUI. Пример:

[_____] [+]

После нажатия на кнопку [+]:

[_____]
[_____] [+]

Чтобы все усложнить, я бы хотел добавить поле пар , чтобы оно выглядело так:

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

Как сохранить доступность простой встроенной проверки и назначить методы при реализации этой функции? Нужна ли подчиненная форма? Мне нужно что-то еще? После отправки формы код должен иметь возможность сопоставлять поля и массив.

Боюсь, мне нужно создать подкласс Zend_Form или SubForm, но я хочу знать, какой самый простой / самый красивый способ.

Ответы [ 3 ]

1 голос
/ 23 декабря 2009

Самый простой подход здесь заключается в использовании простого пользовательского Zend Validator, который будет анализировать входные элементы, поскольку весь массив PHP видит это так, что вы можете выполнить следующее автоматически.

  1. Проверка каждого элемента ввода независимо и отображение сообщений об ошибках, связанных с каждым элементом.
  2. Возвращение массива с возможностью разбора, чтобы перестроить только что отправленную форму.

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

Это позволит вам проверять любое количество произвольных элементов ввода по мере необходимости без необходимости подформирования или беспокоиться о необходимости повторного добавления элементов формы, если и когда произойдет сбой произвольного элементапроверка и должна быть перестроена на стороне клиента.

0 голосов
/ 13 февраля 2010

Вот мое собственное решение: Я создал два скрытых поля, одно для ключей, одно для значений. Кусок кода javascript создает поддельные пары полей в deamand, а в onChange он отображает все поддельные поля в скрытые, используя JSON. Это легко обрабатывать на стороне сервера, но используемая техника javascript не является дискретной.

0 голосов
/ 22 декабря 2009

Вот как добавить десять полей ввода, каждое из которых имеет 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. и т.д.
...