Как «проверить» форму Symfony по шагам - вместо вызова $ form-> isValid () - PullRequest
2 голосов
/ 23 августа 2010

Я использую Symfony 1.3.6 в Ubuntu.

У меня есть форма с множеством полей - вместо того, чтобы показывать все поля за один раз (что может пугать пользователя), я хочуразбить форму на этапы, чтобы пользователь мог заполнять только отображаемые поля на каждом этапе / этапе (вроде как мастер).

Для этого мне нужно написать собственные методыдля формы, например:

validateStep1();
validateStep2();
...
validate StepN();

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

Для этого было бы полезно, если бы я мог вызвать метод isValid () для виджетов, однако я посмотрел на классы sfWidget и такого уровня не существует на уровне виджетов.

Я не хочу выполнять жесткую проверку кода для каждого виджета, который я использую, поскольку это не DRY

Кто-нибудь знает, как я могу проверить отдельные виджеты в форме дляпосмотреть, введено ли пользователем значение (с)) действительны?

Ответы [ 2 ]

3 голосов
/ 24 августа 2010

Я бы использовал другой метод для реализации многочастных форм в Symfony.Надеемся, что для запуска вам достаточно следующей оболочки.

Шаг 1: добавьте виджет сцены в вашу форму

public function configure()
{
  $this->setWidget('stage', new sfWidgetFormInputHidden(array('default' => 1));
  $this->setValidator('stage', new sfValidatorFormInteger(array('min' => 1, 'max' => $maxStages, 'required' => true));
}

Шаг 2: Добавитьнекоторая информация о этапах в вашей форме

protected $stages = array(
  1 => array('stage1field1', 'stage1field2',
  2 => array('stage2field1', ... //etc for as many stages you have
);

Шаг 3: Добавьте метод настройки как этап в вашу форму

public function configureAsStage($currentStage)
{
  foreach($this->stages as $stage => $field)
  {
    if ($currentStage > $stage)
    {
      $this->setWidget($stage, new sfWidgetFormInputHidden()); //so these values carry through
    }
    if ($stage > $currentStage)
    {
       unset($this[$stage]); //we don't want this stage here yet
    }
  }
}

Шаг 4: Переопределить doBind

Возможно, вам придется переопределить bind() напрямую, я забыл.

public function doBind(array $taintedValues)
{
  $cleanStage = $this->getValidator('stage')->clean($taintedValues['stage']);
  $this->configureAsStage($cleanStage);
  parent::doBind($taintedValues);
}

Шаг 5: Добавьте некоторые вспомогательные методы в форму

public function advanceStage()
{
  if ($this->isValid())
  {
    $this->values['stage'] += 1;
    $this->taintedValues['stage'] += 1;
    $this->resetFormFields();
  }
}

public function isLastStage()
{
  return $this->getValue('stage') == count($this->stages);
}

Шаг 6. Вызовите configureAsStage / advanceStage по мере необходимости в вашем действии

public function executeNew(sfWebRequest $request)
{
  $form = new MultiStageForm($record);
  $form->configureAsStep(1);
}

public function executeCreate(sfWebRequest $request)
{
  $record = new Record();
  $form = new MultiStageForm($record);
  $form->bind($request[$form->getName()]);
  if ($form->isValid())
  {
    if ($form->isLastStage())
    {
      $form->save();
      //redirect or whatever you do here
    }
    $form->advanceStage(); 
  }
  //render form
}

Я сделал это полностью на лету.Я думаю, что это должно работать, но я не проверял это, поэтому могут быть некоторые ошибки!

1 голос
/ 23 августа 2010

Функция isValid() на самом деле ничего не делает, кроме проверки того, была ли связана связанная форма и общее количество ошибок валидатора равно 0. Фактическая проверка выполняется на этапе «связывания» ($form->bind()).

После привязки ошибки валидатора сохраняются в каждом поле формы (sfFormField).Итак, чтобы получить отдельные ошибки полей формы, вы можете сделать что-то вроде этого:

<?php
  foreach ($form as $formField) { // $formField is an instance of sfFormField
    if ($formField->hasError()) {
      // do something
    }
  }
?>

Или, так как в вашем случае вам нужно иметь дело только с ограниченным набором полей, попробуйте выполнить итерацию повместо этого массив имен полей:

<?php
  $fieldNames = array('name', 'email', 'address');
  foreach ($fieldNames as $fieldName) {
    if ($form[$fieldName]->hasError()) {
      // do something
    }
  }
?>

Это можно легко адаптировать к функции, скажем validateFields($fieldNames), которая соответствует ожиданиям DRY.

Проверьте документацию для sfFormField чтобы узнать, какую другую информацию вы можете получить из поля.

...