Как «проверить» форму Symfony в шагах – вместо вызова $ form-> isValid ()

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

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

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

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

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

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

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

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

Я бы использовал другой метод для реализации многочастных форм в 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 } } } с 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 } 

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

Функция 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, чтобы узнать, какую другую информацию вы можете получить из поля.