Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine many-to-many relationship wants to create a table twice when I create a migration

Before I describe my problem, it might actually make it clearer if I start with the error I'm getting:

$ ./app/console doc:mig:diff

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

That's absolutely true - user_media_area does exist. I created it in a previous migration and I don't understand why Symfony is trying to create the table again.

My problem has something to do with a many-to-many relationship. I have a table called user, a table called media_area and a table called user_media_area.

Here's the code where I tell user about media_area (Entity/User.php):

/**
 * @ORM\ManyToMany(targetEntity="MediaArea", inversedBy="mediaAreas")
 * @JoinTable(name="user_media_area",
 *      joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@JoinColumn(name="media_area_id", referencedColumnName="id")}
 *      )
 */
private $mediaAreas;

And here's where I tell media_area about user (Entity/MediaArea.php):

/** 
 * @ORM\ManyToMany(targetEntity="User", mappedBy="users")
 */
private $users;

What's interesting is that if I remove that JoinTable stuff from Entity/User.php, ./app/console doctrine:migrations:diff will work again:

/**
 * @ORM\ManyToMany(targetEntity="MediaArea", inversedBy="mediaAreas")
 */
private $mediaAreas;

However, it's a little off: it now wants to create a new table called mediaarea, which I don't want. My table already exists and it's called media_area.

So it looks like either way, Symfony is trying to create a table based on this ManyToMany thing in my User class, and the only reason the problem goes away when I remove the JoinTable is that the name of the table it wants to create (mediaarea) no longer matches the actual name of my table (media_area).

So my question is: Why does it want to create a new table at all? What am I doing wrong?

(I know it's possible that my naming conventions are off. Symfony and Doctrine's database examples are frustratingly devoid of multi-term column names, so I don't always know if I'm supposed to do media_area or mediaArea.)

like image 650
Jason Swett Avatar asked Mar 28 '12 22:03

Jason Swett


1 Answers

According to the Association Mapping explanation on the official docs, the @JoinColumn and @JoinTable definitions are usually optional and have sensible default values, being:

name: "<fieldname>_id"
referencedColumnName: "id"

From that we can conclude that there is really no concrete difference between the two implementations you presented.

However, when it comes to migration, the creation of the table is a pretty common and expected behaviour. The thing is the table should always get deleted and created again, which is not happenning.

About the table name issue, the default behaviour of Doctrine 2 about this:

/**
 * @ORM\ManyToMany(targetEntity="MediaArea", inversedBy="mediaAreas")
 */
private $mediaAreas;

Is to try and create a table called mediaarea. Again, perfectly normal.

If you want to declare a specific name for the table of an entity, you should do this:

/**
 * @ORM\Table(name="my_table")
 */
class Something

I'm not sure if that helps you at all, but I guess it puts you, at least, on the right track.

like image 107
Daniel Ribeiro Avatar answered Sep 28 '22 06:09

Daniel Ribeiro