Doctrine orm 如何从反面编辑/更新Symfony 3中的多对多关系

Doctrine orm 如何从反面编辑/更新Symfony 3中的多对多关系,doctrine-orm,many-to-many,php-5.6,symfony3.x,Doctrine Orm,Many To Many,Php 5.6,Symfony3.x,我正在编写一个bash脚本,它使用一些工具和Symfony 3 bin/console原则创建了一个简单的项目“从零到积垢”:* 它工作得很好,但是在M:N关联的情况下,我不能从相反的方面更新数据。 我在这里读了一些答案,并开始了一些测试,但我对“cascade={“all”}”选项、“by_reference'=>false”和其他建议感到困惑。 从这个取自官方条令文件的基本例子开始,最简单的方法是什么 /** @Entity */ class User { // ...

我正在编写一个bash脚本,它使用一些工具和Symfony 3 bin/console原则创建了一个简单的项目“从零到积垢”:* 它工作得很好,但是在M:N关联的情况下,我不能从相反的方面更新数据。 我在这里读了一些答案,并开始了一些测试,但我对“cascade={“all”}”选项、“by_reference'=>false”和其他建议感到困惑。 从这个取自官方条令文件的基本例子开始,最简单的方法是什么

    /** @Entity */
class User {
    // ...

    /**
     * Many Users have Many Groups.
     * @ManyToMany(targetEntity="Group", inversedBy="users")
     */
    private $groups;

    public function __construct() {
        $this->groups = new \Doctrine\Common\Collections\ArrayCollection();
    }

    // ...
}

/** @Entity */
class Group {

    // ...
    /**
     * Many Groups have Many Users.
     * @ManyToMany(targetEntity="User", mappedBy="groups")
     */
    private $users;

    public function __construct() {
        $this->users = new \Doctrine\Common\Collections\ArrayCollection();
    }

    // ...
}

这是一个完整的例子,说明了Symfony和Doctrine中的多对多关系。我通常使用yaml而不是注释。因此,如果需要使用注释,您必须使用注释转换代码

# AppBundle/Entity/User.php
//the id + more fields here if needed
//getters and setters for the other fields

/**
 * @var \Doctrine\Common\Collections\Collection
 */
private $groups;

public function __construct()
{
    $this->groups = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add group
 *
 * @param \AppBundle\Entity\Group $group
 *
 * @return User
 */
public function addGroup(\AppBundle\Entity\Group $group)
{
    if ($this->groups->contains($group)) {
        return;
    }

    //those two lines of code are the one you are seeking for, for saving both the owning side and the inverse side
    $this->groups[] = $group;
    $group->addUser($this);

    return $this;
}

/**
 * Remove group
 *
 * @param \AppBundle\Entity\Group $group
 */
public function removeGroup(\AppBundle\Entity\Group $group)
{
    if (!$this->groups->contains($group)) {
        return;
    }

    //those are the lines for removing the owning side and the inverse side
    $this->groups->removeElement($group);
    $group->removeUser($this);
}

/**
 * Get groups
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getGroups()
{
    return $this->groups;
}

# AppBundle/Resources/config/doctrine/User.orm.yml
AppBundle\Entity\User:
type: entity
table: users
repositoryClass: AppBundle\Repository\UserRepository
id:
    id:
        type: integer
        id: true
        generator:
            strategy: AUTO
manyToMany:
    groups:
        targetEntity: AppBundle\Entity\Group
        inversedBy: users
        joinTable:
            name: groups_users
            joinColumns:
                user_id:
                    referencedColumnName: id
                    nullable: true
            inverseJoinColumns:
                group_id:
                    referencedColumnName: id
        cascade: ['persist', 'remove']
        fetch: EAGER
fields:
    # more fields here if needed
lifecycleCallbacks: {  }

# AppBundle/Entity/Group.php
//the id + more fields here if needed
//getters and setters for the other fields

/**
 * @var \Doctrine\Common\Collections\Collection
 */
private $users;

public function __construct()
{
    $this->users = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add user
 *
 * @param \AppBundle\Entity\User $user
 *
 * @return Group
 */
public function addUser(\AppBundle\Entity\User $user)
{
    if ($this->users->contains($user)) {
        return;
    }

    //these lines saves both the inverse side and the owning side
    $this->users[] = $user;
    $user->addGroup($this);

    return $this;
}

/**
 * Remove user
 *
 * @param \AppBundle\Entity\User $user
 */
public function removeUser(\AppBundle\Entity\User $user)
{
    if (!$this->users->contains($user)) {
        return;
    }

    //these lines remove both the inverse side and the owning side
    $this->users->removeElement($user);
    $user->removeGroup($this);
}

/**
 * Get users
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getUsers()
{
    return $this->users;
}

# AppBundle/Resources/config/doctrine/Group.orm.yml
AppBundle\Entity\Group:
type: entity
table: groups
repositoryClass: AppBundle\Repository\GroupRepository
id:
    id:
        type: integer
        id: true
        generator:
            strategy: AUTO
manyToMany:
    users:
        targetEntity: AppBundle\Entity\User
        mappedBy: groups
        cascade: ['persist']
        fetch: EAGER
fields:
    # more fields here if needed
lifecycleCallbacks: {  }
我希望我没有犯任何错误,因为我将我的本地
类别
-
产品
示例改编为您的

接下来,您需要在每个表单类型中都有一个字段,以便能够为用户选择组,为组选择用户

# AppBundle/Form/UserType.php
$builder
    ->add('name') // this is a field I used in my local example, you can add yours
    ->add('groups', EntityType::class, [
        'class' => 'AppBundle:Group',
        'placeholder' => 'Choose a Group',
        'query_builder' => function (EntityRepository $er) {
            return $er->createQueryBuilder('g')
                ->orderBy('g.name', 'DESC');
        },
        'choice_label' => 'name',
        'multiple'=>true,
        'expanded'=>false,
        'by_reference' => false,
    ])

# AppBundle/Form/GroupType.php
$builder
    ->add('name')
    ->add('users', EntityType::class, [
        'class' => 'AppBundle:User',
        'placeholder' => 'Choose User',
        'query_builder' => function (EntityRepository $er) {
            return $er->createQueryBuilder('u')
                ->orderBy('u.name', 'DESC');
        },
        'choice_label' => 'name',
        'multiple'=>true,
        'expanded'=>false,
        'by_reference' => false,
    ])

在更新模式之前,您需要创建两个实体,而不需要任何映射。然后更新模式,然后继续创建实体之间的多对多关系,并再次更新模式以应用该关系。试一试,让我们知道它是否有效。

这里有一个关于Symfony和Doctrine中多对多关系的完整示例。我通常使用yaml而不是注释。因此,如果需要使用注释,您必须使用注释转换代码

# AppBundle/Entity/User.php
//the id + more fields here if needed
//getters and setters for the other fields

/**
 * @var \Doctrine\Common\Collections\Collection
 */
private $groups;

public function __construct()
{
    $this->groups = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add group
 *
 * @param \AppBundle\Entity\Group $group
 *
 * @return User
 */
public function addGroup(\AppBundle\Entity\Group $group)
{
    if ($this->groups->contains($group)) {
        return;
    }

    //those two lines of code are the one you are seeking for, for saving both the owning side and the inverse side
    $this->groups[] = $group;
    $group->addUser($this);

    return $this;
}

/**
 * Remove group
 *
 * @param \AppBundle\Entity\Group $group
 */
public function removeGroup(\AppBundle\Entity\Group $group)
{
    if (!$this->groups->contains($group)) {
        return;
    }

    //those are the lines for removing the owning side and the inverse side
    $this->groups->removeElement($group);
    $group->removeUser($this);
}

/**
 * Get groups
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getGroups()
{
    return $this->groups;
}

# AppBundle/Resources/config/doctrine/User.orm.yml
AppBundle\Entity\User:
type: entity
table: users
repositoryClass: AppBundle\Repository\UserRepository
id:
    id:
        type: integer
        id: true
        generator:
            strategy: AUTO
manyToMany:
    groups:
        targetEntity: AppBundle\Entity\Group
        inversedBy: users
        joinTable:
            name: groups_users
            joinColumns:
                user_id:
                    referencedColumnName: id
                    nullable: true
            inverseJoinColumns:
                group_id:
                    referencedColumnName: id
        cascade: ['persist', 'remove']
        fetch: EAGER
fields:
    # more fields here if needed
lifecycleCallbacks: {  }

# AppBundle/Entity/Group.php
//the id + more fields here if needed
//getters and setters for the other fields

/**
 * @var \Doctrine\Common\Collections\Collection
 */
private $users;

public function __construct()
{
    $this->users = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add user
 *
 * @param \AppBundle\Entity\User $user
 *
 * @return Group
 */
public function addUser(\AppBundle\Entity\User $user)
{
    if ($this->users->contains($user)) {
        return;
    }

    //these lines saves both the inverse side and the owning side
    $this->users[] = $user;
    $user->addGroup($this);

    return $this;
}

/**
 * Remove user
 *
 * @param \AppBundle\Entity\User $user
 */
public function removeUser(\AppBundle\Entity\User $user)
{
    if (!$this->users->contains($user)) {
        return;
    }

    //these lines remove both the inverse side and the owning side
    $this->users->removeElement($user);
    $user->removeGroup($this);
}

/**
 * Get users
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getUsers()
{
    return $this->users;
}

# AppBundle/Resources/config/doctrine/Group.orm.yml
AppBundle\Entity\Group:
type: entity
table: groups
repositoryClass: AppBundle\Repository\GroupRepository
id:
    id:
        type: integer
        id: true
        generator:
            strategy: AUTO
manyToMany:
    users:
        targetEntity: AppBundle\Entity\User
        mappedBy: groups
        cascade: ['persist']
        fetch: EAGER
fields:
    # more fields here if needed
lifecycleCallbacks: {  }
我希望我没有犯任何错误,因为我将我的本地
类别
-
产品
示例改编为您的

接下来,您需要在每个表单类型中都有一个字段,以便能够为用户选择组,为组选择用户

# AppBundle/Form/UserType.php
$builder
    ->add('name') // this is a field I used in my local example, you can add yours
    ->add('groups', EntityType::class, [
        'class' => 'AppBundle:Group',
        'placeholder' => 'Choose a Group',
        'query_builder' => function (EntityRepository $er) {
            return $er->createQueryBuilder('g')
                ->orderBy('g.name', 'DESC');
        },
        'choice_label' => 'name',
        'multiple'=>true,
        'expanded'=>false,
        'by_reference' => false,
    ])

# AppBundle/Form/GroupType.php
$builder
    ->add('name')
    ->add('users', EntityType::class, [
        'class' => 'AppBundle:User',
        'placeholder' => 'Choose User',
        'query_builder' => function (EntityRepository $er) {
            return $er->createQueryBuilder('u')
                ->orderBy('u.name', 'DESC');
        },
        'choice_label' => 'name',
        'multiple'=>true,
        'expanded'=>false,
        'by_reference' => false,
    ])

在更新模式之前,您需要创建两个实体,而不需要任何映射。然后更新模式,然后继续创建实体之间的多对多关系,并再次更新模式以应用该关系。试试看,让我们知道它是否有效。

它有效!非常感谢。在buildForm()中的键是“by_reference”=>false('multiple'=>true),正如本页所述:(显然需要添加“use Symfony\Bridge\Doctrine\Form\Type\EntityType;”在class GroupType中)它可以工作!非常感谢。正如本页所述,buildForm()中的键是“by_reference”=>false('multiple'=>true):(显然需要在类GroupType中添加“use Symfony\Bridge\Doctrine\Form\Type\EntityType;”