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