Embedded forms not saving default values

58 views
Skip to first unread message

Kye Etherton

unread,
Apr 15, 2012, 9:38:14 AM4/15/12
to diem-users
Hi all, I have a three tiered form for answering survey questions.
Basically it works by having 'pages' which contain questions. For each
question it makes an 'answer' form, and the answer then embedded
another form depending on the question type.

After working on it for several days now and slowly reducing the
amount of bugs (embedded forms are evil) I now have a problem where
the answers form seams to have data in it at the actions.class.php
level, but not when it tries to save.


Survey section form - embeddeds one answer form per question
<code class="php"><pre>abstract class PluginSurveySectionForm extends
BaseSurveySectionForm {

public function setup() {
parent::setup();

$subForm = new sfForm();

foreach ($this->object->getSurveyQuestion() as $surveyQuestion) {
$answer = Doctrine_Core::getTable('SurveyAnswer')-
>createQuery('s')
->where('s.question = ?', $surveyQuestion->get('id'))
->andWhere('s.dmuser = ?', sfContext::getInstance()-
>getUser()->getDmUser())
->fetchOne();

$form = new SurveyAnswerForm($answer, array('survey_question' =>
$surveyQuestion));

$subForm->embedForm($surveyQuestion, $form);
}
unset($this['title']);
$this->embedForm('Questions', $subForm);
}

protected function doSave($con = null)
{
if (null === $con) {
$con = $this->getConnection();
}

$this->saveEmbeddedForms($con);

}

public function saveEmbeddedForms($con = null, $forms = null) {
if (null === $forms) {
$Questions = $this->getValue('Questions');
$forms = $this->embeddedForms;

foreach ($this->embeddedForms['Questions'] as $name => $form) {

if (!isset($Questions[$name])) {
unset($forms['Questions'][$name]);
}else if(!isset($Questions[$name])){

}
}
}

return parent::saveEmbeddedForms($con, $forms);
}

}</pre></code>

Answer form - embeddeds an answer form depending on the type of
question and sets default values
<code class="php"><pre>abstract class PluginSurveyAnswerForm extends
BaseSurveyAnswerForm {

public function setup() {
parent::setup();

$type = $this->getValue('type');

if (is_null($type)) {
if (!$SurveyQuestion = $this->getOption('survey_question')) {
throw new InvalidArgumentException('You must provide a
question object.');
} else {
$type = $SurveyQuestion->get('type');
$this->setDefault('type', $type);
$this->setDefault('question', $SurveyQuestion->get('id'));
$this->setDefault('dmuser', sfContext::getInstance()-
>getUser()->getDmUser()->get('id'));
}
}

$this->widgetSchema['type'] = new sfWidgetFormInputHidden();
$this->widgetSchema['question'] = new sfWidgetFormInputHidden();
$this->widgetSchema['dmuser'] = new sfWidgetFormInputHidden();

$this->setValidators(array(
'id' => new sfValidatorChoice(array('choices' =>
array($this->getObject()->get('id')), 'empty_value' => $this-
>getObject()->get('id'), 'required' => false)),
'type' => new sfValidatorChoice(array('choices' => array(0 =>
'Integer', 1 => 'String', 2 => 'Float', 3 => 'Text', 4 => 'Boolean', 5
=> 'Files'), 'required' => false)),
'question' => new sfValidatorDoctrineChoice(array('multiple' =>
false, 'model' => 'SurveyQuestion', 'required' => false)),
'dmuser' => new sfValidatorDoctrineChoice(array('multiple' =>
false, 'model' => 'dmUser', 'required' => false)),
));

switch ($type) {
case "Integer":
$this->embedForm('result', new SurveyIntegerForm());
$this->validatorSchema['result']['value'] = new
sfValidatorInteger(array('required' => false));
break;
case "String":
$this->embedForm('result', new SurveyStringForm());
$this->validatorSchema['result']['value'] = new
sfValidatorString(array('required' => false));
break;
case "Float":
$this->embedForm('result', new SurveyFloatForm());
$this->validatorSchema['result']['value'] = new
sfValidatorNumber(array('required' => false));
break;
case "Text":
$this->embedForm('result', new SurveyTextForm());
$this->validatorSchema['result']['value'] = new
sfValidatorString(array('required' => false));
break;
case "Boolean":
$this->embedForm('result', new SurveyBooleanForm());
$this->validatorSchema['result']['value'] = new
sfValidatorChoice(array('choices' => array(0 => 'N/A', 1 => 'No', 2 =>
'Yes'), 'required' => false));
break;
case "Files":
$this->embedForm('result', new SurveyFilesForm());
break;
}
}

public function saveEmbeddedForms($con = null, $forms = null)
{
if (null === $forms)
{
$result = $this->getValue('result');
$forms = $this->embeddedForms;

foreach ($this->embeddedForms['result'] as $name => $form)
{
if (!isset($result[$name]))
{
unset($forms['result'][$name]);
}
}
}
//die();
return parent::saveEmbeddedForms($con, $forms);
}
}</pre></code>

survey actions.class.php
<code class="php"><pre>
class surveySectionActions extends myFrontModuleActions
{

public function executeShowWidget(dmWebRequest $request)
{
$form = new SurveySectionForm($this->getPageRecord());

if ($request->isMethod('post') && $request->hasParameter($form-
>getName()))
{
$results = $request->getParameter($form->getName());

foreach($results["Questions"] as $question => $answer){
var_dump(($results["Questions"][$question]));die();
}

if ($form->bindAndValid($request))
{
$this->getUser()-
>setFlash('exta_day_added_successfully',true);

$form->save();

$this->redirectBack();
}
}

$this->forms['SurveySection'] = $form;
}
}</pre></code>

Above var_dump produces:

array(5) { ["result"]=> array(2) { ["value"]=> string(1) "1" ["id"]=>
string(0) "" } ["id"]=> string(0) "" ["type"]=> string(7)
"Integer" ["dmuser"]=> string(1) "1" ["question"]=> string(2) "42" }

I'm fairly sure the above it correct. The dmuser and question are both
the ID's because it says the answer is invalid otherwise. However
without the die in the above code I get:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(`duediligence`.`survey_answer`, CONSTRAINT
`survey_answer_dmuser_dm_user_id` FOREIGN KEY (`dmuser`) REFERENCES
`dm_user` (`id`))

It is trying to save:

at Doctrine_Connection->exec('INSERT INTO survey_answer (type,
created_at, updated_at) VALUES (?, ?, ?)', array('String', '2012-04-15
14:36:19', '2012-04-15 14:36:19'))
in SF_ROOT_DIR/lib/vendor/diem/symfony/lib/plugins/sfDoctrinePlugin/
lib/vendor/doctrine/lib/Doctrine/Connection.php line 687 ...
at Doctrine_Connection->insert(object('SurveyAnswerTable'),
array('type' => 'String', 'created_at' => '2012-04-15 14:36:19',
'updated_at' => '2012-04-15 14:36:19'))
in SF_ROOT_DIR/lib/vendor/diem/symfony/lib/plugins/sfDoctrinePlugin/
lib/vendor/doctrine/lib/Doctrine/Connection/UnitOfWork.php line
647 ...

Why is it forgetting the values that are set in the form? Without it
having the user and question the object it's not going to save, and
would be useless if it did!

Any help or advise is appreciated.

Thank you

Kye

Kye Etherton

unread,
Apr 18, 2012, 12:02:56 PM4/18/12
to diem-users
Don't worry, solved it all.

José Antonio Sánchez Bedoya

unread,
Jun 15, 2012, 1:13:28 PM6/15/12
to diem-...@googlegroups.com
Kye Etherton we have the same problem and can't solved. Which is the solution? Thanks

Kye Etherton

unread,
Jun 15, 2012, 1:46:12 PM6/15/12
to diem-...@googlegroups.com
Erm I kinda saved each form manually in the admin menu cause I gave up looking for the right method.

Stéphane

unread,
Jun 16, 2012, 9:14:54 PM6/16/12
to diem-...@googlegroups.com
Remember how the embedding is working.

When you call embedForm, the method is cloning every fields of the given form.
So when calling _embedForm->save() in the doSave() of the embedding form, you have to, before calling this, feed the embeddingForm with values (doUpdateEmbeddedForm or something similar) because the fields of the embedded forms and the fields in the embedding form "representing" the embedded form are distinct objects !

You'd better put breakpoints and follow the white rabbit to see how things are going to play well with form embedding.

Regards

Roozbeh Baabakaan

unread,
Jun 19, 2012, 7:10:42 AM6/19/12
to diem-...@googlegroups.com
hi !

i have the same problem , and this issue seems that it's not only limited in admin app !

after days of thinking and asking and searching , i found the best answer :
 
       act form as flat php !



Stéphane

unread,
Jun 19, 2012, 8:00:14 AM6/19/12
to diem-...@googlegroups.com
oO

Kye Etherton

unread,
Jun 19, 2012, 8:01:16 AM6/19/12
to diem-...@googlegroups.com
I agree with steph,


Yours Sincerely

Kye Etherton
Managing Director

Sugar Cube Productions Ltd

Company Registered in England and Wales, registration number: 07856043

Roozbeh Baabakaan

unread,
Jun 19, 2012, 8:29:29 AM6/19/12
to diem-...@googlegroups.com
+1


Kye    

  and 


Stéphane



Reply all
Reply to author
Forward
0 new messages