How to save embedded forms in symfony 1?

734 views Asked by At

I have a form which represnts single answer object (this is standard propel generated form I have not changed much there only some validation rules) and another form that represents a collection of answers code as below:

class BbQuestionAnswersForm extends sfForm {

  public function __construct($defaults = array(), $options = array(), $CSRFSecret = null) {
    parent::__construct($defaults, $options, $CSRFSecret);
  }

  public function configure() {
    if (!$questions = $this->getOption('questions')) {
      throw new InvalidArgumentException('The form need array of BbExamQuestion objects.');
    }
    if (!$taker = $this->getOption('taker')) {
      throw new InvalidArgumentException('The form need BbExamtaker object.');
    }
    if (!$user = $this->getOption('questions')) {
      throw new InvalidArgumentException('The form need sfGuardUser object.');
    }

    foreach($questions as $question) {
      $answer = new BbExamAnswer();
      $answer->setBbExamQuestion($question);
      $answer->setBbExamTaker($taker);
      $answer->setCreatedBy($user);
      $answer->setUpdatedBy($user);
      $form = new BbExamAnswerForm($answer, array('question' => $question));

      $this->embedForm($question->getId(), $form);
    }

    $this->widgetSchema->setNameFormat('solve[%s]');
  }
}

Everything(validation, display) goes fine with this form until I try to save it. Part of action which trying to save the form:

...
    $this->form = new BbQuestionAnswersForm(null, array('questions' => $this->questions, 'taker' => $this->taker, 'user' => $this->getUser()->getGuardUser()));
    if($request->isMethod('post')) {
      $this->form->bind($request->getParameter($this->form->getName()));
      if($this->form->isValid()) {
        if($this->form->save()) {
          $this->getUser()->setFlash('success', 'Save goes fine.');
          $this->redirect($this->generateUrl('@bb'));
        } else {
          $this->getUser()->setFlash('error', 'Upps an error occurred.');
        }
      }
    }

When I send valid form I receive "Call to undefined method BbQuestionAnswersForm::save()" error.

I tried to write this method like this:

public function save() {
    $conn = Propel::getConnection(ZlecPeer::DATABASE_NAME);
    $conn->beginTransaction();
    try{
      foreach($this->getEmbeddedForms() as $form) {
        $form->save();
      }
      $conn->commit();
    } catch(Exception $e) {
      $conn->rollback();
      echo 'upps something goes wrong';
      die($e->getMessage());
      return false;
    }
    return true;
  }

but it doesnt work, I receive exception without any message.

What am I doing wrong, how to make save method work?

2

There are 2 answers

0
Agrest On BEST ANSWER

Save method should looks like this:

public function save($con = null) {
    if (null === $con) {
      $con = Propel::getConnection(BbExamAnswerPeer::DATABASE_NAME);
    }
    $con->beginTransaction();
    try{
      foreach($this->embeddedForms as $name => $form) {
        if(!isset($this->values[$name]) || !is_array($this->values[$name])) {
          continue;
        }
        if($form instanceof sfFormObject) {
          $form->updateObject($this->values[$name]);
          $form->getObject()->save($con);
          $form->saveEmbeddedForms($con);
        } else {
          throw new Exception('Embedded form should be an instance of sfFormObject');
        }
      }
      $con->commit();
    } catch(Exception $e) {
      $con->rollBack();
      throw $e;
      return false;
    }

    return true;
  }
0
dotcomly On

I believe your BbQuestionAnswersForm is extending the wrong object. It should extend BaseFormDoctrine or possibly BaseBbQuestionAnswersForm if you are using the framework correctly.

Edit: Just noticed you are using propel but it should be the same thing. Try:

class BbQuestionAnswersForm extends BaseBbQuestionAnswersForm

and less likely:

class BbQuestionAnswersForm extends BaseFormPropel