开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜