Symfony2 Doctrine2 多对多形式不保存实体

发布于 2025-01-02 08:13:52 字数 870 浏览 2 评论 0原文

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

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

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

I am having some trouble with a many to many relationship. I have Users and Assets. I would like to be able to assign users to an asset on the asset page.

The code below displays a list of users when creating/editing an asset, however changes made to the user checkboxes do not save, while the rest of the data is persisted.

If I add an entry to users_assets through the mysql client, these changes are shown in the asset list.

User

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

Asset

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

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

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

发布评论

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

评论(5

月竹挽风 2025-01-09 08:13:52

由于某种原因,我必须切换学说映射才能使其正常工作:

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

不太确定为什么我需要在资产与用户上拥有 inversedBy 和 JoinTable 信息,但它现在似乎可以正常工作!

感谢您的建议!

For some reason I had to switch the doctrine mappings to get this to work:

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;

Now when I save the asset it saves the users associated. I did not need to define builder->add as an entity or collection. I simply pass it null and it uses the mapping info to fill in the entity info:

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

Not exactly sure why I needed to have the inversedBy and JoinTable info on the Asset vs The User but it seems to be working now!

Thanks For The Suggestions!!!

压抑⊿情绪 2025-01-09 08:13:52

奇怪的是,我在 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

AssetType 表单的 users 字段中。

有关此设置的更多信息,请参见http://symfony.com/ doc/current/reference/forms/types/form.html#by-reference

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

Weird enough I faced the same problem in 2016 and still had hard time finding the solution. I will share it for future googlers:

The problem is that what symfony essentially does when you save the form is this:

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

And because you're on the inverse side of the relation it won't persist your changes.

What you really need is to make so that it calls this:

$asset->addUser($user)

Where addUser() is defined the following way on the Asset entity:

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

So in order to make symfony use that $asset->addUser() method, you should set

'by_reference' => false

on your users field for AssetType form.

More about this setting here http://symfony.com/doc/current/reference/forms/types/form.html#by-reference

Remember you also need to define removeUser() method in the same way (so that it removes entity from the owning relation)

_失温 2025-01-09 08:13:52

不太清楚为什么我需要 inversedBy 和
关于资产与用户的 JoinTable 信息,但它
似乎现在正在工作!

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

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

Not exactly sure why I needed to have the inversedBy and
JoinTable info on the Asset vs The User but it
seems to be working now!

The reason why your changes has been ignored is that doctrine persists only changes by the owning side of a relation (like @Florian said).

This is the link to Doctrine's documentation where this behaviour is explained: http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html

治碍 2025-01-09 08:13:52

首先,您应该在注释中删除反斜杠前缀(请参阅通知 此处)。

并且您需要使用实体字段类型:

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

At first you should drop backslash prefix in annotations (see notice here).

And you need to use entity field type:

$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');
    },
));
两人的回忆 2025-01-09 08:13:52

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

$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

You need to use 'collection' field type in your form.

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

You need to create the UserType() form first obviously.

Here is all the info you will need, including code samples:

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

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

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