Doctrine2 ManyToMany插入

时间:2014-03-19 11:46:24

标签: doctrine-orm zend-framework2 many-to-many insert-update

我正在使用Zend Framework 2和Doctrine2。 我有2个具有多对多关系的实体:项目和用户。 Doctrine使用字段project_id和user_id创建了一个表users_projects,因为每个项目可以有多个用户,每个用户可以有多个项目。 现在,当我添加项目时,我想向项目添加多个用户。 那么,如何在表users_projects中插入数据?

项目

class Project {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer", unique=TRUE)
*/
protected $id;
/**
 * @ORM\ManyToMany(targetEntity="User", mappedBy="projects")
 */
protected $users;

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

用户

class User {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer", unique=TRUE)
*/
protected $id;

/**
 * @ORM\ManyToMany(targetEntity="Project", inversedBy="users")
 * @ORM\JoinTable(name="users_projects")
 */
protected $projects;

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

2 个答案:

答案 0 :(得分:2)

  

那么,如何在表users_projects中插入数据?

你没有;)

文件引用:

  

初学者的一个常见错误是将DQL误认为只是某种形式的SQL,因此尝试在查询中使用表名和列名或将任意表连接在一起。您需要将DQL视为对象模型的查询语言,而不是关系模式。

在您的情况下,您不必担心users_projects表,因为您没有对象(实体)。您只有ProjectUser个实体,因此您只需将这些实体相互附加即可。担心连接表是Doctrine的职责。

这是一个很好的方法:

<强>项目

use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity
 */
class Project
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @var int
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="User", mappedBy="projects")
     * @var ArrayCollection
     */
    protected $users;

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

    /**
     * @param User $user
     */
    public function addUser(User $user)
    {
        if (!$this->users->contains($user)) {
            $this->users->add($user);
            $user->addProject($this);
        }
    }

    /**
     * @param User $user
     */
    public function removeUser(User $user)
    {
        if ($this->users->contains($user)) {
            $this->users->removeElement($user);
            $user->removeProject($this);
        }
    }

    /**
     * @return User[]
     */
    public function getUsers()
    {
        return $this->users->toArray();
    }

    // ...
}

用户

use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity
 */
class User
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @var int
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="Project", inversedBy="users")
     * @ORM\JoinTable(name="users_projects")
     * @var ArrayCollection
     */
    protected $projects;

    public function __construct()
    {
        $this->projects = new ArrayCollection();
    }

    /**
     * @param Project $project
     */
    public function addProject(Project $project)
    {
        if (!$this->projects->contains($project)) {
            $this->projects->add($project);
            $project->addUser($this);
        }
    }

    /**
     * @param Project $project
     */
    public function removeProject(Project $project)
    {
        if ($this->projects->contains($project)) {
            $this->projects->removeElement($project);
            $project->removeUser($this);
        }
    }

    /**
     * @return Project[]
     */
    public function getProjects()
    {
        return $this->projects->toArray();
    }

    // ...
}

请注意,Project::getUsers()User::getProjects()不会返回集合本身,而是返回普通的PHP数组。这将确保实体对这些集合中添加/删除的内容具有完全控制

其次,您会看到Project::addUser()不仅会将User添加到其集合中,而且User也会将该Project添加到其集合中。这对于双向关联很重要!双方都需要达成一致,否则可能(并且将会)发生奇怪的事情。

这也适用于从集合中删除。

PS:围绕添加/删除的contains()检查将确保以无限循环结束;)

使用此

// user-table has 0 rows, project-table has 0 rows, join-table has 0 rows

$user = new User();
$project = new Project();

$em->persist($user);
$em->persist($project);

$em->flush();

// user-table has 1 row, project-table has 1 row, join-table has 0 rows

$project->addUser($user);

$em->flush();

// user-table has 1 row, project-table has 1 row, join-table has 1 row

$secondProject = new Project();
$secondProject->addUser($user);

$em->persist($secondProject);
$em->flush();

// user-table has 1 row, project-table has 2 rows, join-table has 2 rows

$user->removeProject($project);

$em->flush();

// user-table has 1 row, project-table has 2 rows, join-table has 1 rows

答案 1 :(得分:0)

关系是ArrayCollection,您希望add您的对象加入此集合。 如下所示:

$project = new Project;
$project->title = 'Foo';

// Create new user
$user = new User;
$user->name = 'Bar';
$user->getProjects()->add($project);
$em->persist($user);

// ..or add to existing user
$existingUser = $userRepo->findById(1);
$existingUser->getProjects()->add($project);
$em->persist($existingUser);

$project->getUsers()->add($user);

$em->persist($project);
$em->flush();