2012-02-01 111 views
18

我在多对多关系中遇到了一些麻烦。我有UsersAssets。我希望能够将用户分配到资产页面上的资产。Symfony2 Doctrine2多对多形式不保存实体

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

如果我通过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; 
} 

AssetType

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

    return $form; 
} 
+0

你不应该chanage'null'到' EntityType'?你是什​​么意思由null?! – Trix 2017-05-09 13:51:29

回答

29

出于某种原因,我不得不切换主义映射得到这个工作:

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->添加为实体或集合。我只是将它传递null,并且它使用映射信息,以填补在实体信息:

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

不知道是什么原因,我需要有inversedBy和资产VS用户JoinTable信息,但它似乎是工作现在!

感谢您的建议!

+0

我有类似的问题。对其他人的建议:确保你所有的单数/复数都是他们应该是的,如果你的任何一个实体有多个术语的名称(例如'CoolDude'),你可能会从知道默认的Doctrine假设你的表名只是它的较低版本,例如'cooldude'。如果它实际上是'cool_dude',我想你必须明确地设置它。你可以看到Doctrine文档中的内容。 http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#many-to-many-bidirectional – 2012-03-28 00:10:37

+0

问题是当你想要一个类似的窗体上反面:它不会工作。 – 2012-05-01 08:58:13

+0

解决方案不适合我,我的连接表总是空的! – Fabien 2014-03-25 10:37:52

0

您需要使用 '收集' 呸ld在你的表单中键入。

$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

+0

我认为通过传递null它会认为这是类型,通过我的教条映射。我有一个类似的设置使用资产的类别,它的效果很好。这是我必须填充类别集合的代码: - > add('categories',null,array('expanded'=>“true”,“multiple”=>“true”))...我也没有需要为资产中的用户添加crud功能,而我只需要能够将当前用户分配给该资产 – 2012-02-01 20:40:43

+1

确实,来自扩展的原则添加了基于元数据的guesser。如果你已经正确定义了ManyToMany关联,那么类型猜测者会将你的字段配置为'collection'。通过*正确*,我的意思是**的所有者**必须是您的情况下的'资产',这就是为什么你必须颠倒你的映射。 – Florian 2012-02-02 18:17:06

+0

'EntityType' +'Expanded' +'Multiple'有什么问题? – Trix 2017-05-09 13:49:06

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'); 
    }, 
)); 
9

奇怪的是我在2016年面临着同样的问题,仍然有很难找到解决方案。我将分享其对未来的Google:

的问题是,什么样的symfony基本上没有当您保存形式是这样的:

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

而且因为你在关系的另一方它将不会坚持你的改变。

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

$asset->addUser($user)

凡ADDUSER()是指对资产实体的方式如下:

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

AssetType表格users场。

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

记住,你还需要以同样的方式来定义removeUser()方法(以便从所属关系删除实体)

+0

这应该是被接受的答案。我想知道,做一些复古发布,为什么没有人写这个,并最终把你与你的。好一个。 – DonCallisto 2016-09-15 09:22:09

+0

**资产**在此拥有一方,因此这与[Doctrine Documentation](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#拥有和反对在一个许多tomany协会) – Trix 2017-05-09 13:44:50

+0

@Trix谢谢,我刚刚再次检查,确实有用户/资产混淆。我做了一个编辑 - 解决方案仍然是一样的,我只调整了变量名称以保持一致。 – 2017-05-11 15:17:59

相关问题