2012-03-28 2 views
11

Prima di descrivere il mio problema, potrebbe effettivamente rendere più chiaro se comincio con l'errore che sto ricevendo:Dottrina molti-a-molti vuole creare un tavolo per due volte quando creo una migrazione

$ ./app/console doc:mig:diff 

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

Questo è assolutamente vero - user_media_area esiste. L'ho creato in una precedente migrazione e non capisco perché Symfony stia cercando di creare nuovamente la tabella.

Il mio problema ha qualcosa a che fare con una relazione molti-a-molti. Ho un tavolo chiamato user, un tavolo chiamato media_area e un tavolo chiamato user_media_area.

Ecco il codice in cui dico user circa 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; 

E qui è dove dico media_area circa user (Entity/MediaArea.php):

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

La cosa interessante è che se rimuovo che il materiale JoinTable da Entity/User.php, ./app/console doctrine:migrations:diff funzionerà di nuovo:

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

Tuttavia, è un po 'spento: ora vuole creare un nuovo tavolo chiamato mediaarea, che non desidero. Il mio tavolo esiste già e si chiama media_area.

così sembra che in entrambi i casi, Symfony sta cercando di creare una tabella basata su questo ManyToMany cosa nella mia classe User, e l'unico motivo per il problema scompare quando rimuovo il JoinTable è che il nome della tabella che vuole creare (mediaarea) non corrisponde più al nome effettivo del mio tavolo (media_area).

Quindi la mia domanda è: Perché vuole creare un nuovo tavolo? Che cosa sto facendo di sbagliato?

(so che è possibile che le mie convenzioni di denominazione sono spenti. Symfony e gli esempi di database di Doctrine sono frustrante prive di nomi di colonne multi-termine, quindi non sempre sanno se io dovrei fare media_area o mediaArea.)

risposta

4

Secondo il Association Mapping spiegazione sui documenti ufficiali, i @JoinColumn e @JoinTable definizioni sono di solito opzionali e hanno valori di default ragionevoli, essendo:

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

da che si può concludere che non vi è davvero nessuna differenza concreta tra le due implementazioni che hai presentato.

Tuttavia, quando si tratta di migrazione, la creazione della tabella è un comportamento piuttosto comune e previsto. La cosa è che il tavolo dovrebbe sempre essere cancellato e creato di nuovo, il che non è affatto felice.

Circa la questione del nome tabella, il comportamento predefinito di Doctrine 2 su questo:

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

è cercare di creare una tabella chiamata mediaarea. Di nuovo, perfettamente normale.

Se si desidera dichiarare un nome specifico per la tabella di un'entità, si dovrebbe fare questo:

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

Non sono sicuro se questo ti aiuta a tutti, ma credo che vi pone, almeno, sulla strada giusta.

+3

Perché è contrassegnato come risposta? Non risponde alla domanda dell'OP su come impedire alla dottrina di mostrare quell'errore. Dopo averlo aggiunto, ho ottenuto Doctrine \ Common \ Annotations \ AnnotationException: [Errore semantico] @ORM \ Table non può essere dichiarato sulla proprietà User :: $ mediaAreas. È possibile utilizzare questa annotazione solo su questi elementi di codice: CLASS. – jaycode

+0

Si sta provando a inserire l'annotazione '@ ORM/Tabella' a livello di proprietà, mentre dovrebbe essere posizionata a livello di classe. L'errore non ha nulla a che fare con la domanda o la risposta. –

+0

L'annotazione corretta è @ ORM/JoinTable – luliandro