【问题标题】:Symfony2 Doctrine2 Many To Many Form not Saving EntitiesSymfony2 Doctrine2 多对多形式不保存实体
【发布时间】:2012-02-01 19:36:03
【问题描述】:

我在多对多关系方面遇到了一些麻烦。我有UsersAssets。我希望能够将用户分配给资产页面上的资产。

以下代码在创建/编辑资产时显示用户列表,但是对用户复选框所做的更改不会保存,而其余数据会保留。

如果我通过 mysql 客户端向 users_assets 添加条目,这些更改会显示在资产列表中。

用户

class User extends BaseUser
{
    /**
     * @ORM\ManyToMany(targetEntity="Asset", inversedBy="users")
     */
    private $assets;
}

资产

class Asset
{
    /**
     * @ORM\ManyToMany(targetEntity="User", mappedBy="assets")
     */
    private $users;
}

资产类型

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $form = $builder
        ->add('users', null, array(
            'expanded' => true,
            'multiple' => true
        ))
        ->getForm();

    return $form;
}

【问题讨论】:

  • 您不应该将null 更改为EntityType 吗?你说的 null 是什么意思?!

标签: forms symfony many-to-many doctrine-orm


【解决方案1】:

出于某种原因,我不得不切换学说映射以使其正常工作:

Asset:
 /**
 * @ORM\ManyToMany(targetEntity="Adaptive\UserBundle\Entity\User", inversedBy="assets")
 * @ORM\JoinTable(name="user_assets")
 */
private $users;

User:
 /**
 * @ORM\ManyToMany(targetEntity="Splash\SiteBundle\Entity\Asset", mappedBy="users")
 */
private $assets;

现在,当我保存资产时,它会保存关联的用户。我不需要将 builder->add 定义为实体或集合。我只是将它传递给 null,它使用映射信息来填写实体信息:

AssetType:
->add('users', null, array('expanded' => "true", "multiple" => "true"))

不完全确定为什么我需要在 Asset vs The User 上获得 inversedBy 和 JoinTable 信息,但它现在似乎可以工作了!

谢谢你的建议!!!

【讨论】:

  • 我遇到了类似的问题。给其他人的建议:确保你所有的单数/复数都是它们应该是的,如果你的任何一个实体有一个多词名称(例如CoolDude),你可能会因为知道 Doctrine 默认是假设您的表名只是它的小写版本,例如cooldude。如果它实际上是cool_dude,我认为您必须明确设置它。你可以在 Doctrine 文档中看到如何。 docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/…
  • 问题是当你想要一个类似的形式在反面:它不起作用。
  • @slaapwagen 这里有同样的问题。它不会在反面工作。您是否已经找到解决此问题的方法?
【解决方案2】:

奇怪的是,我在 2016 年遇到了同样的问题,但仍然很难找到解决方案。我会分享给未来的谷歌人:

问题是当你保存表单时 symfony 的本质是这样的:

$asset->getUsers()->add($user)

而且由于您处于关系的反面,因此不会保留您的更改。

你真正需要的是让它这样调用:

$asset->addUser($user)

addUser() 在 Asset 实体上的定义方式如下:

public function addUser(User $user) 
{
    //add to the inverse side
    $this->users->add($user);

    //add on the owning side (only this is persisted)
    $user->addAsset($this); //$user->assets->add($asset);
}

所以为了让 symfony 使用 $asset->addUser() 方法,你应该设置

'by_reference' => false

在您的users 字段中,用于AssetType 表单。

更多关于这个设置的信息在这里http://symfony.com/doc/current/reference/forms/types/form.html#by-reference

请记住,您还需要以相同的方式定义 removeUser() 方法(以便从拥有关系中删除实体)

【讨论】:

  • 这应该是公认的答案。我在想,做一些复古的帖子,为什么没有人写这个,最后还是和你一起来了。不错。
  • 资产 在这里拥有方,因此这与Doctrine Documentation 冲突
  • @Trix 谢谢,我刚刚再次检查过,确实存在用户/资产混淆。我进行了编辑 - 解决方案仍然相同,我只是将变量名称调整为一致。
【解决方案3】:

不完全确定为什么我需要 inversedBy 和 资产与用户的 JoinTable 信息,但它 似乎现在正在工作!

您的更改被忽略的原因是,学说仅由关系的拥有方更改(如@Florian 所说)。

这是解释此行为的 Doctrine 文档的链接:http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html

【讨论】:

    【解决方案4】:

    首先你应该在注释中去掉反斜杠前缀(见通知here)。

    而且你需要使用实体字段类型:

    $builder->add('users', 'entity', array(
        'class' => 'AdaptiveUserBundle:User',
        'expanded' => true,
        'multiple' => true,
        'query_builder' => function(EntityRepository $er) {
            return $er->createQueryBuilder('u')
                ->orderBy('u.username', 'ASC');
        },
    ));
    

    【讨论】:

      【解决方案5】:

      您需要在表单中使用“收藏”字段类型。

      $builder->add('users', 'collection', array(
          'type' => new UserType(),
          'prototype' => true,
          'allow_add' => true,
          'allow_delete' => true
      ));
      

      显然你需要先创建UserType() 表单。

      以下是您需要的所有信息,包括代码示例:

      http://symfony.com/doc/current/cookbook/form/form_collections.html

      http://symfony.com/doc/current/reference/forms/types/collection.html

      【讨论】:

      • 我认为通过传递 null 它会假设这是类型,通过我的学说映射。我在资产上使用类别进行了类似的设置,并且效果很好。这是我必须填充类别集合的代码: ->add('categories', null, array('expanded' => "true", "multiple" => "true" ))... 我也没有需要为资产中的用户添加 crud 功能,而我只需要能够将当前用户分配给该资产
      • 确实,扩展的学说添加了一个基于元数据的猜测器。如果您正确定义了多对多关联,类型猜测器会将您的字段配置为collection正确,我的意思是关联的所有者在您的情况下必须是Asset,这就是您必须反转映射的原因。
      • EntityType+Expanded+Multiple有什么问题?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多