Albert Iskhakov
Albert Iskhakov

Reputation: 229

Many-to-many relation in Doctrine2 leads to duplication error in migration

I have made two Doctrine2 entities in my project which is based on the Symfony2 framework. This entities has many-to-many relation. There are my models:

/**
 * @ORM\Entity
 * @ORM\Table(name="first")
 */
class First
{
    ...

    /**
     * @var Second[]|Collection
     *
     * @ORM\ManyToMany(targetEntity="MyBundle\Entity\Second", cascade={"detach"})
     * @ORM\JoinTable(name="first_to_second",
     *      joinColumns={@ORM\JoinColumn(name="first_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="second_id", referencedColumnName="id")},
     * )
     */
    private $seconds;

    ...
}

/**
 * @ORM\Entity
 * @ORM\Table(name="second")
 */
class Second
{
    ...

    /**
     * @var First[]|Collection
     *
     * @ORM\ManyToMany(targetEntity="MyBundle\Entity\First", cascade={"remove"})
     * @ORM\JoinTable(name="first_to_second",
     *      joinColumns={@ORM\JoinColumn(name="second_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="first_id", referencedColumnName="id")},
     * )
     */
    private $firsts;

    ...
}

When I try to make migration

$ php app/console doctrine:migration:diff

there is an error:

[Doctrine\DBAL\Schema\SchemaException]
The table with name 'first_to_second' already exists.

Upvotes: 2

Views: 761

Answers (1)

1ed
1ed

Reputation: 3668

The field definitions are wrong. You should define the JoinTable only one side (the owning side) of the relation and define which side is which by mappedBy and inversedBy.

http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-many-bidirectional

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

    /**
     * @ManyToMany(targetEntity="Group", inversedBy="users")
     * @JoinTable(name="users_groups")
     */
    private $groups;

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

    // ...
}

/** @Entity */
class Group
{
    // ...
    /**
     * @ManyToMany(targetEntity="User", mappedBy="groups")
     */
    private $users;

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

    // ...
}

5.9.1. Owning and Inverse Side on a ManyToMany association

For Many-To-Many associations you can chose which entity is the owning and which the inverse side. There is a very simple semantic rule to decide which side is more suitable to be the owning side from a developers perspective. You only have to ask yourself, which entity is responsible for the connection management and pick that as the owning side.

Upvotes: 3

Related Questions