Symfony Forms Framework: Change validators at runtime.

Warning! This post is either deprecated or outdated.

Let’s say you have to make a user form with password fields. When you create the user you want the password fields to be required, but on an update the password fields should be optional because you don’t want the user the fill in his password on each update.

This is tricky because in the symfony forms Framework you have to predefine your validators. Your form would look like this:

class UserForm extends BaseUserForm {

  public function configure() {
    // Widgets
    $this->widgetSchema['password'] = new sfWidgetFormInputPassword();
    $this->widgetSchema['password_again'] = new sfWidgetFormInputPassword();

    // Validators
    $this->validatorSchema['password']->setOption('required', false);
    $this->validatorSchema['password_again'] = clone $this->validatorSchema['password'];

    $this->widgetSchema->moveField('password_again', 'after', 'password');

    $this->mergePostValidator(new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_again', array(), array('invalid' => 'The two passwords must be the same.')));
  }

}

In this signature of the form I defined the password and password_again field as optional, which is correct for an update of the user, but incorrect for the creation of the user. How the hell can I change the validator of the password field when I create a user ?

Well thanks to the good and well designed framework of symfony it is very simple :).

class UserForm extends BaseUserForm {

  public function configure() {
    // Widgets
    $this->widgetSchema['password'] = new sfWidgetFormInputPassword();
    $this->widgetSchema['password_again'] = new sfWidgetFormInputPassword();

    // Validators
    $this->validatorSchema['password']->setOption('required', false);
    $this->validatorSchema['password_again'] = clone $this->validatorSchema['password'];

    $this->widgetSchema->moveField('password_again', 'after', 'password');

    $this->mergePostValidator(new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_again', array(), array('invalid' => 'The two passwords must be the same.')));
  }

  public function bind(array $taintedValues = null, array $taintedFiles = null) {

    if ( $this->object->isNew() ) {
      $this->validatorSchema['password']->setOption('required', true);
    }

    parent::bind($taintedValues, $taintedFiles);
  }

}

What I did is override the function bind and before calling the bind method of the parent, I checked if the user object is new (means that we create a user) and if this is the case set the required option of the password field to true.

By the way, if you found a typo, please fork and edit this post. Thank you so much! This post is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Comments

Fork me on GitHub