Ask your Symfony questions! Pay money and get answers fast! (more info)

Embedded i18n form in an embedded relation creates 2 records Symfony

Symfony 1.4
Propel (with sfPropel15Plugin)

I have a multilanguage Gallery with the following schema:

# Galleries
pi_gallery:
_attributes:
phpName: Gallery
isI18N: true
i18nTable: pi_gallery_i18n
_propel_behaviors:
sortable: ~
id: ~
active:
type: boolean
default: true
required: true
created_at: ~
updated_at: ~

pi_gallery_i18n:
_attributes:
phpName: GalleryI18n
id:
type: integer
foreignTable: pi_gallery
foreignReference: id
required: true
primaryKey: true
onDelete: cascade
culture:
isCulture: true
type: varchar
size: 7
required: true
primaryKey: true
name:
type: varchar
size: 255
required: false
description:
type: longvarchar
required: false

# Images
pi_gallery_image:
_attributes:
phpName: GalleryImage
isI18N: true
i18nTable: pi_gallery_image_i18n
id: ~
gallery_id:
type: integer
foreignTable: pi_gallery
foreignReference: id
required: true
image:
type: varchar
size: 255
required: true
created_at: ~
updated_at: ~

pi_gallery_image_i18n:
_attributes:
phpName: GalleryImageI18n
id:
type: integer
foreignTable: pi_gallery_image
foreignReference: id
required: true
primaryKey: true
onDelete: cascade
culture:
isCulture: true
type: varchar
size: 7
required: true
primaryKey: true
description:
type: varchar
size: 255
required: false


I'm trying to embed the Image forms in the Gallery using the following:


# GalleryForm.class

public function configure()
{
unset(
$this['alias'],
$this['created_at'],
$this['updated_at']
);

$this->widgetSchema['article_id']->setOption('renderer_class', 'sfWidgetFormPropelJQueryAutocompleter');
$this->widgetSchema['article_id']->setOption('renderer_options', array(
'model' => 'Article',
'url' => '/article/ajax'
));

$this->validatorSchema['article_id'] = new sfValidatorPass();

$this->embedI18n(array('es', 'en', 'de', 'it', 'fr'));

$this->widgetSchema->setLabel('en','English');
$this->widgetSchema->setLabel('es','Español');
$this->widgetSchema->setLabel('de','Deutsch');
$this->widgetSchema->setLabel('it','Italiano');
$this->widgetSchema->setLabel('fr','Francais');

$this->embedRelation('GalleryImage'); // Embeds the Relation between the GalleryImage model and the Gallery Model
}


and in GalleryImageForm.class:

public function configure()
{
unset(
$this['created_at'],
$this['updated_at'],
$this['gallery_id'],
$this['sortable_rank']
);

if ($this->isNew()) unset($this['id']);

$this->embedI18n(array('es', 'en', 'de', 'it', 'fr'));

$image = $this->getObject()->getImage();
$template = (!is_null($image) || $image != "") ? '<div>%file%<br />%input%<br />%delete% %delete_label%</div>' : '';

$this->widgetSchema['image'] = new sfWidgetFormInputFileEditable(array(
'label' => 'Imagen',
'file_src' => '/'.sfConfig::get('sf_upload_dir_name').'/images/galleries/thumbs/'.substr($this->getObject()->getImage(),0,-4) . '.jpg',
'is_image' => true,
'edit_mode' => !$this->isNew() && $image != "",
'with_delete' => true,
'delete_label'=>'Eliminar archivo existente',
'template' => $template
));

$this->validatorSchema['image_delete'] = new sfValidatorPass();

$this->validatorSchema['image'] = new sfValidatorFile(array(
'path' => sfConfig::get('sf_upload_dir').'/images/galleries',
'required' => false,
'mime_types' => 'web_images'
));
}


This appears to embed the forms as expected ... initially. The GalleryForm appears with Multilanguage Descriptions and the ImageForms embed beneath them. So far so good.

Saving the form however shows that all is not good.

Two records are saved initially, one with just the image and the other with just the i18n fields. The i18n fields also have the id of the second record added so there is no way of relating the image to the i18n fields. Maybe the order of saving the forms is wrong?

Has anyone successfully got a form to work that embeds I18n in an embedded Relation? Or does anyone have any idea of a workaround? I've read about something about overriding saveEmbeddedForms but I don't even know where to start with that.

Any help appreciated.

Answers (1)

2011-05-06

Łukasz Adamczeewski answers:

I start my work with embeded relations with putting some code in BaseDoctrineForm. I don't know if this solution will work with BasePropelForm and generaly propel ORM but you should try.




public function bindEmbeddedForms($embedded_forms, $values)
{
if ($this->isValid())
{
foreach ($embedded_forms as $name => $form)
{
$form->isBound = true;
$form->values = $values[$name];


if ($form->embeddedForms)
{
$this->bindEmbeddedForms($form->embeddedForms, $values[$name]);
}
}
}
}



This is universal aproach to save embeded forms. The reason why child form is not working as you expect is because there is no call to bind method of any embeded forms so the subforms values are not bound and saved to values property

You need also add this code to your parent form:


public function bind(array $taintedValues = null, array $taintedFiles = null)
{

parent::bind($taintedValues, $taintedFiles);
$this->bindEmbeddedForms($this->embeddedForms, $this->getValues());
}


You should also read about this problem on [[LINK href="http://stereointeractive.com/blog/2008/12/23/symfony-12-upload-a-file-inside-an-embedded-form/"]][[/LINK]]


Adam Frame comments:

Thank you for your effort but your solution had no effect whatsoever.

It still saves 2 records.

Maybe someone knows of a Propel specific solution?



Łukasz Adamczeewski comments:

I accidently submit message.

I forgot to mention that when we want to save embeded form we need to unset foreign_key field in parent form that is linked with child object.

unset($this['foreign_table_id'])

I found propel solution for embeding form on this blog

[[LINK href="http://www.thatsquality.com/articles/embedding-child-forms-with-sfformpropel-a-practical-example"]][[/LINK]]





Łukasz Adamczeewski comments:

This message system here is really annoing because it hide my link for blog above, if it is still not visible use view source from your browser. [[LINK href="http://www.thatsquality.com/articles/embedding-child-forms-with-sfformpropel-a-practical-example"]][[/LINK]]


Adam Frame comments:

Thank you again for your help. I have already seen the site you suggest but unfortunately it was not helpful.

If you notice I am using sfPropel15Plugin which uses version 1.5 of Propel. This version negates the need for such extra overriding (supposedly) by using embedRelation().

I am specifically looking for a solution that uses embedRelation and then allows embedding i18n child forms.

Thank you again.