symfony 嵌入式形式的多对多

发布于 2024-10-26 23:21:40 字数 1651 浏览 4 评论 0原文

我对模型中的嵌入表单有问题,它具有多对多关系。嵌入表单将正确保存模型,但不会保存多对多关系。

示例:

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

然后我只需修改 MotherForm.class.php:

class MotherForm extends BaseMotherForm
{
  public function configure()
  {
    $this->embedForm('child', new ChildForm($this->getObject()->getChildren()));
  }
}

和 ChildForm.class.php:

class ChildForm extends BaseChildForm
{
  public function configure()
  {
    unset($this['mother_id']);
  }
}

我用学说生成模块:

php symfony doctrine:generate-module frontend mother Mother

放置一些颜色数据:

Color:
  Color_1:
    name: blue
  Color_2:
    name: red
  Color_3:
    name: green
  Color_4:
    name: purple

当我调用 /frontend_dev.php/mother/new 时,我可以添加新的,母亲和孩子的名字被更新,但最喜欢的颜色永远不会保存...

如果我使用 phpmyadmin 添加颜色和孩子之间的关系,然后 /edit 调用。然后正确的颜色是在多重选择中选择的,但我无法编辑它。

这是 Symfony 的错误还是我应该做其他事情?

更新: 如果我为模型 Child 生成模块。我可以编辑最喜欢的颜色,但表单不再嵌入......

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 color 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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦里南柯 2024-11-02 23:21:40

我也遇到过和你一样的问题。 symfony 中的 Ticket #5867 就是关于这个问题的,很多人都丢失了很多时间用它。

在票证中,有人给出了解决方案。你可以尝试一下,但我不知道为什么它们对我的情况不起作用。

我已经成功使用了在这篇文章中找到的解决方案 。这是一篇非常有用的帖子,解释了此错误的原因和解决方法。

基本上,该错误是由于保存嵌入表单时,symfony 在嵌入对象中调用 save() ,而不是在嵌入表单中调用 save()对象中的内容不会更新相关表。

要解决这个问题,您必须覆盖 //lib/form/doctrine/BaseFormDoctrine.class.php (或 Propel 等效项,但然后在以下代码中用 Doctrine 替换 Propel):

创建函数 bindEmbeddedForms () 这种方式:

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]);
      }
    }
  }
}

声明 bind() 函数调用其父函数,这种方式:

public function bind(array $taintedValues = null, array $taintedFiles = null)
{
   parent::bind($taintedValues, $taintedFiles);
   $this->bindEmbeddedForms($this->embeddedForms, $this->getValues());
}

并覆盖 saveEmbeddedForms()这种方式:

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());
    }
  }
}

然后,在您的嵌入式表单类中(在帖子中,它也在 BaseFormDoctrine 类中执行此操作,但我认为它更干净),创建方法 doSaveManyToMany 来保存您的关系:

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)
}

有些人说有帖子评论中出现了一些问题并提出了解决方案,但这不是我的情况。

希望它对某人有所帮助,即使我的答案是针对一个相当古老的未解决问题。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文