How to 'validate' a Symfony form in steps - instead of calling $form->isValid()

后端 未结 2 605
野性不改
野性不改 2021-02-04 22:07

I am using Symfony 1.3.6 on Ubuntu.

I have a form with a lot of fields on it - rather than showing all the fields in one go (which may intimidate the user), I want to br

相关标签:
2条回答
  • 2021-02-04 22:49

    The function isValid() doesn't really do anything, except check if the associated form has been bound and that the total number of validator errors is 0. The actual validation is done during the "binding" stage ($form->bind()).

    After binding, validator errors are stored in each field of the form(sfFormField). So, to get the individual errors of form fields, you can do something like this:

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

    Or, since in your case you need to deal with only a restricted set of fields, try to iterate over an array of field names instead:

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

    This can easily be adapted into a function, say validateFields($fieldNames) that meets DRY expectations.

    Check the documentation for sfFormField to see what other information you can get from a field.

    0 讨论(0)
  • 2021-02-04 22:50

    I would utilize a different method to implement multi part forms in Symfony. Hopefully, the following shell is enough to get you started.

    Step 1: Add a stage widget to your form

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

    Step 2: Add some information about the stages to your form

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

    Step 3: Add a configure as stage method to your form

    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
        }
      }
    }
    

    Step 4: Override doBind

    You might need to override bind() directly, I forget.

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

    Step 5: Add some auxiliary methods to the form

    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);
    }
    

    Step 6: Call configureAsStage/advanceStage as necessary in your action

    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
    }
    

    I made this up completely on the fly. I think it should work, but I haven't tested it so there may be some mistakes!

    0 讨论(0)
提交回复
热议问题