symfony many to many in embedded form
I have a problem with embbed form from Model which has many to many relation. The embedded form will save the model correctly but will not save many to many relations.
Example:
Schema.yml:
Mother:
columns:
name:
type: string(80)
Color:
columns:
name:
type: string(80)
Child:
columns:
mother_id:
type: integer
name:
type: string(80)
relations:
Mother:
class: Mother
local: mother_id
foreign: id
type: one
onDelete: cascade
foreignType: one
foreignAlias: Children
FavoriteColors:
class: Color
refClass: ChildColor
local: child_id
foreign: color_id
onDelete: cascade
foreignAlias: Children
ChildColor:
columns:
child_id:
type: integer
color_id:
type: integer
Then I just modify MotherForm.class.php:
class MotherForm extends BaseMotherForm
{
public function configure()
{
$this->embedForm('child', new ChildForm($this->getObject()->getChildren()));
}
}
and ChildForm.class.php:
class ChildForm extends BaseChildForm
{
public function configure()
{
unset($this['mother_id']);
}
}
I generate the module with doctrine:
php symfony doctrine:generate-module frontend mother Mother
Put some color data:
Color:
Color_1:
name: blue
Color_2:
name: red
Color_3:
name: green
Color_4:
name: purple
When I call /frontend_dev.php/mother/new I can add a new one, name of Mother and Child are updated but favorite c开发者_开发知识库olor are never saved...
If I add a relation between a color and a child with phpmyadmin and then /edit call. Then the right color is in the multiple select selected, but I can't edit it.
Is it a bug from Symfony or should I do something else ?
UPDATE: If I generate the module for the model Child. I can edit favorite colors but the form is not embedded anymore...
I have had the same issue than you. Ticket #5867 in symfony is all about this issue, and a lot of people have lost a lot of time with it.
In the ticket, some people give solutions. You can try them, but I don't know why they didn't work in my case.
I have suceed with a solution found in this post. It's a very useful post, which explains the reason of this bug and a workaround.
Basically, the bug is due to the fact that when saving embedded forms, symfony calls save()
in the embedded object, but not in the embedded form, and save()
in an object doesn't update related tables.
To solve it you must overwrite //lib/form/doctrine/BaseFormDoctrine.class.php
(or the Propel equivalent, but then substitue Doctrine for Propel in following code):
Create the function bindEmbeddedForms()
this way:
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]);
}
}
}
}
Declare bind()
function calling its parent one this way:
public function bind(array $taintedValues = null, array $taintedFiles = null)
{
parent::bind($taintedValues, $taintedFiles);
$this->bindEmbeddedForms($this->embeddedForms, $this->getValues());
}
And overwrite saveEmbeddedForms()
this way:
public function saveEmbeddedForms($con = null, $forms = null)
{
if (is_null($con))
{
$con = $this->getConnection();
}
if (is_null($forms))
{
$forms = $this->embeddedForms;
}
foreach ($forms as $key => $form)
{
if ($form instanceof sfFormDoctrine)
{
if(method_exists(new $form(), 'doSaveManyToMany'))
{
$form->doSaveManyToMany($con);
}
else
{
$form->getObject()->save($con);
}
$form->saveEmbeddedForms($con);
}
else
{
$this->saveEmbeddedForms($con, $form->getEmbeddedForms());
}
}
}
Then, in your embedded form class (in the post it do this as well in BaseFormDoctrine
class, but I think it's cleaner my way), create the method doSaveManyToMany
which save your relations:
public function doSaveManyToMany($con = null)
{
if (is_null($con))
{
$con = $this->getConnection();
}
$this->object->save($con);
/*
* Save the many-2-many relationship
*/
$this->save***List($con); //Ex: $this->saveAhasBList($con)
}
Some people say to have some problem in the post comments and say a solution, but it wasn't my case.
Hope it helps somebody, even if my answer is for a quite old opened question.
精彩评论