Форма Symfony 1.4, условная выдача sfValidatorError во встроенной форме - PullRequest
3 голосов
/ 17 декабря 2010

У меня есть объект Page:

Page:
  actAs:
    Timestampable: ~
    I18n:
      fields: [name,content,attachment,course_name, course_description ]
      actAs:
        Sluggable: { fields: [name], uniqueBy: [lang, name], canUpdate: true }
  columns:
  ...
    is_course:            { type: boolean }
    course_name:          { type: string(255) }
    course_description:   { type: string(500) }

И PageForm со встроенными формами i18n:

//PageForm.class.php 
public function configure()
{
...  
    $this->embedI18n(array('pl','en'));
    $this->widgetSchema->setLabel('en', 'Angielski');
    $this->widgetSchema->setLabel('pl', 'Polski');
}

Поля course_name и course_description не требуются, в то время как is_course имеет значение false. Но если is_course включен, валидация должна выдать ошибку о том, что course_name и course_description необходимы.

Я прочитал руководство "Расширенные формы Symfony" и некоторые другие сообщения, но я не знаю, должен ли я использовать sfValidatorCallback в PageForm или PostValidator в PageTranslationForm? Я попытался использовать sfValidatorCallback таким образом:

//PageForm.class.php
public function configure()
{
...
       $this->validatorSchema->setPostValidator(
          new sfValidatorCallback(array('callback' => array($this,'checkCourses')))
          );
}

public function checkCourses($validator, $values)
{
    if($values['is_course'])
    {
      if($values['pl']['course_name'] && !$values['pl']['course_description'])
      {
          $error = new sfValidatorError($validator,'Required filed');
          throw new sfValidatorErrorSchema($validator, array( _what_name_ => $error));
      }
    }
    return $values;
}

Но я не знаю, как выдавать ошибку в $ values ​​['pl'] ['course_description'], потому что API Symfony говорит, что _what_name_ должно быть массивом ошибок ..

Я действительно запутался, что происходит во время проверки форм в Symfony.

// Edit

Я сделал некоторые изменения в PageTranslationForm, и теперь это выглядит так ... //PageTranslationform.class.php

 public function configure()
 {
 //......

  $this->validatorSchema->setPostValidator(
          new sfValidatorCallback(array('callback' => array($this,'checkCourses')))
   );

 //.....
 }

public function checkCourses($validator, $values)
{
    if($values['course_name'] && !$values['course_description'])
    {
        $error = new sfValidatorError($validator,'Required');
        throw new sfValidatorErrorSchema($validator, array( 'course_description' => $error));
    }
    elseif(!$values['course_name'] && $values['course_description'])
    {
        $error = new sfValidatorError($validator,'Required');
        throw new sfValidatorErrorSchema($validator, array( 'course_name' => $error));

    }
    return $values;
}

И это почти работает, но ... этот валидатор должен быть включен, только если в PageForm is_course имеет значение "true". Как я могу получить доступ к полю "is_course" из PageForm в функции checkCourses в PageTranslationForm?

// РЕШЕНИЕ

Спасибо, Джереми, я воспользовался твоей идеей и, наконец, получил это решение:

//PageForm.class.php
public function configure()
{
    $this->embedI18n(array('pl','en'));
    $this->widgetSchema->setLabel('en', 'Angielski');
    $this->widgetSchema->setLabel('pl', 'Polski');

//.....
  if($this->getObject()->getIsCourse())
  {
      foreach($this->getEmbeddedForms()  as $key => $form)
      {
          $this->validatorSchema[$key]->setPostValidator(
             new sfValidatorCallback(array('callback' => array($form,'checkCourses')))
          );
      }
  }
}

//PageTranslationForm.class.php
//configure etc

  public function checkCourses($validator, $values)
  {
       $errorSchema =  new sfValidatorErrorSchema($validator);


        if($values['course_name'] && !$values['course_description'])
        {
          $errorSchema->addError(new sfValidatorError($validator,'required'), 'course_description');
        }
        elseif(!$values['course_name'] && $values['course_description'])
        {
          $errorSchema->addError(new sfValidatorError($validator,'required'), 'course_name');
        }
        elseif(!$values['course_name'] && !$values['course_description'])
        {
          $errorSchema->addError(new sfValidatorError($validator,'required'), 'course_name');
          $errorSchema->addError(new sfValidatorError($validator,'required'), 'course_description');
        }


        if (count($errorSchema))
        {
          throw new sfValidatorErrorSchema($validator, $errorSchema);
        }

      return $values;
  }

Спасибо за ваш совет, он отлично работает, и я надеюсь, что это будет полезно:)

1 Ответ

2 голосов
/ 17 декабря 2010

Это должен быть пост-валидатор, потому что вы используете несколько значений.

При проверке с помощью пост-валидатора вы можете выдать ошибку двумя разными способами:

Глобально

Когда ошибка генерируется глобально, она будет отображаться как часть sfForm::renderGlobalErrors.Чтобы вывести глобально, просто сгенерируйте ошибку в обратном вызове:

public function checkCourses($validator, $values)
{
  if ($invalid)
  {
    throw new sfValidatorError($validator, 'Required.'); //global messages should be more specific than this
  }
}

Локально

Чтобы ошибка отображалась локально, создайте схему с массивом, какты делаешь.Ключи массива будут определять поля, на которых отображаются ошибки.Это, вероятно, хотите, чтобы вы хотели здесь.

public function checkCourses($validator, $values)
{
  if ($invalid)
  {
    $error = new sfValidatorError($validator,'Required filed');
    throw new sfValidatorErrorSchema($validator, array('course_description' => $error));
  }
}
...