1

1:n の埋め込みフォームを持つ SymfonyForm があります。メイン フォームとembedForm クラスには、条件付き検証を実装する独自の PreValidation があります。EmbedForm クラスの一部は次のようになります。

private function configurePreValidators() {
    $validator = new sfValidatorCallback( array('callback'=> array($this, 'preValidation')) );
    $this->getValidatorSchema()->setPreValidator(new sfValidatorOr( array( $validator ) ));
}

public function preValidation(sfValidatorCallback $validator, array $values){
...
    $this->getValidator(self::SOME_FIELD)->setOption('required', false);
...
}
public function configure() {
    ...
    $this->configurePreValidators();
    parent::configure();
}

メイン フォームの事前検証も同様です。

フォームを送信すると、メイン フォームの事前検証が正常に機能します。

埋め込みフォームでは、「SOME_FIELD」は必要な検証エラーを取得しますが、埋め込みフォームの preValidation で明示的にsetOption('required', false)に設定しました。

埋め込みフォームで事前検証を使用するときに考慮しなければならないことはありますか? mergePreValidatorはどうですか?それについてのヒントはありますか?

前もって感謝します!

4

1 に答える 1

3

The issue here is not that your pre and post validators aren't firing -- they are (or at least, they should be). The issue is that the validator you are modifying is preValidate is not the one referenced in the top-level validator schema, i.e. the validator schema for the top-level form.

One solution: rather than modify the validator in preValidate, simply perform the validation:

public function preValidation(sfValidatorCallback $validator, array $values)
{
  if (!$this->getValidator(self::SOME_FIELD)->isEmpty($values[self::SOME_FIELD])
  {
    throw new sfValidatorErrorSchema(self::SOME_FIELD => new sfValdiatorError($validator, 'msg'));
  }
}

Note, this solution has some danger: if you modify the validator for SOME_FIELD inside of the top-level form, it will not be modified in this pre validator and vice-versa.

Let's look at why. In sfForm::embedForm:

public function embedForm($name, sfForm $form, $decorator = null)
{
  ...
  $this->validatorSchema[$name] = $form->getValidatorSchema();
  ...
}

Symfony simply nests the validators. This is why pre and post still get called. Why does the reference change? sfValidatorSchema::offsetSet:

public function offsetSet($name, $validator)
{
  ...    
  $this->fields[$name] = clone $validator;
}

So when a form is embedded, the validator schema is cloned. Thus, any modifications to the validators inside of an embedded form do not affect the top-level validator schema.

于 2010-12-09T19:45:03.837 に答える