Un post validator pour gérer les dépendances entre les champs

0 gravatar Par Grégoire Marchal - 18/04/2011

Aujourd'hui, je partage un post validator qui permet de définir des dépendances entre des champs. Il permet par exemple de définir que le champ postal_code n'est requis que si le champ country vaut FR.

Voici donc cette classe :

/**
 * sfValidatorSchemaDependency allows to define dependency between fields
 */
class sfValidatorSchemaDependency extends sfValidatorSchema
{
  
  /**
   * Constructor.
   *
   * Available options:
   *
   *  * affected_field:  The field that is required or not
   *  * expected_values: A key/value array that represents the fields and their value
   *                     that must be matched to set the affected_field as required
   *
   * @param string $affected_field   The field that is required or not
   * @param array  $expected_values  A key/value array that represents the fields and their value
   *                                 that must be matched to set the affected_field as required
   * @param array  $options          An array of options
   * @param array  $messages         An array of error messages
   *
   * @see sfValidatorBase
   */
  public function __construct($affected_field, $expected_values, $options = array(), $messages = array())
  {
    $this->addOption('affected_field', $affected_field);
    $this->addOption('expected_values', $expected_values);

    parent::__construct(null, $options, $messages);
  }

  /**
   * @see sfValidatorBase
   */
  protected function doClean($values)
  {
    if (null === $values)
    {
      $values = array();
    }

    if (!is_array($values))
    {
      throw new InvalidArgumentException('You must pass an array parameter to the clean() method');
    }

    $affected_field = isset($values[$this->getOption('affected_field')]) ? $values[$this->getOption('affected_field')] : null;
    
    $bAllValuesMatched = true;
    foreach ($this->getOption('expected_values') as $field => $value)
    {
      // if a field has not the expected value
      if (!isset($values[$field]) || $values[$field] != $value)
      {
        $bAllValuesMatched = false;
        break;
      }
    }

    // if every field has the expected value, and affected_field not defined
    if ($bAllValuesMatched && !$affected_field)
    {
      // "affected_field is required" error
      throw new sfValidatorErrorSchema($this, array(
        $this->getOption('affected_field') => new sfValidatorError($this, 'required')
      ));
    }

    return $values;
  }
}

Et voici comment l'utiliser dans le cas de l'exemple de notre introduction :

  /**
   * @see sfForm::configure()
   */
  public function configure()
  {
    // ...
    $this->mergePostValidator(new sfValidatorSchemaDependency('postal_code', array('country' => 'FR')));
  }
Ainsi, lors de la validation du formulaire, si le champ country vaut FR et si le champ postal_code est vide, une sfValidatorError de type required va être liée au champ postal_code. Notez qu'il est possible de définir plusieurs dépendances, en passant plusieurs éléments dans le tableau en second paramètre du constructeur de sfValidatorSchemaDependency.

Retour à l'accueil

Commentaires (0)

Commenter