Home > Symfony > Conditional Validation in Symfony Forms

Conditional Validation in Symfony Forms

I recently had call to create a form that performed validation on some of it’s fields conditionally, requiring one set of fields if a toggle was marked, another set if not.  After getting it all set up I thought some of you out there might find it useful (and I’m pretty sure I’m going to come looking for this again eventually) so here you go.

First I registered a post callback validator with a new function I created in my form class:

public function configure() {
  ...

  $this->mergePostValidator(new sfValidatorCallback(array('callback' => array($this, 'checkConditionalRequirements'))));
}

Then in my new function I create a new error schema and re-run validation on all fields that I determine should be required based on the current data:

  public function checkConditionalRequirements($validator, $values, $arguments) {
    // container for errors that arise
    $errorSchema = new sfValidatorErrorSchema($validator);
    // list of required fields that we're building
    $required = array();

    // only require a password on new objects
    if($this->getObject()->isNew()) {
      array_push($required, 'password');
    }

    // register appropriate required fields based on current form context
    if($values['condition_field'] == '1') {
      array_push($required, 'field_one', 'field_two');
    }
    else {
      array_push($required, 'field_three');
    }

    // re-process validation on all marked fields
    foreach($required as $field) {
      $this->validatorSchema[$field]->setOption('required', true);
      try {
        $this->validatorSchema[$field]->clean($values[$field]);
      }
      catch(sfValidatorErrorSchema $e) {
        $errorSchema->addErrors($e);
      }
      catch(sfValidatorError $e) {
        $errorSchema->addError($e, $field);
      }
    }

    // if something went wrong let's return it to the currently running validation process in a form it will understand
    if(count($errorSchema)) {
      throw $errorSchema;
    }

    // return clean values
    return $values;
  }

That’s it, and it can be easily extended to re-run validation against more than just requirements.

Categories: Symfony Tags:
  1. No comments yet.
  1. No trackbacks yet.