Nel mio progetto Symdony2 ho due entità correlate: Servizio e Gruppo di servizi. Questa dovrebbe essere una relazione molti-a-molti, perché ogni gruppo può avere molti servizi e ogni servizio può appartenere a molti gruppi. Inoltre, ho bisogno di un'interfaccia utente per gestire servizi e gruppi. Quindi, quando si modifica un servizio, l'utente dovrebbe essere in grado di scegliere a quali gruppi appartiene. Analogamente, quando si modifica un utente del gruppo di servizio dovrebbe essere in grado di scegliere quali servizi appartengono a questo gruppo. Ho già raggiunto questo risultato creando una relazione Molti-A-Molti nelle mie entrate di Doctrine. Tutto funziona come un incantesimo, inclusa l'interfaccia utente costruita su tipi di modulo personalizzati in Symfony2 (ho usato il tipo di campo modulo "entità" per consentire all'utente di selezionare servizi nell'editor e gruppi di ServiceGroup nell'editor Servizio). L'unico problema che ho è che non posso usare la riga di comando di Doctrine per aggiornare più lo schema del database.Symfony2 Doctrine2 Relazione molti-a-molti con due strumenti di linea cmd di proprietà e Doctrine
Ecco parte della mia Service codice sorgente di entità:
class Service
{
/**
* @var ArrayCollection $groups
* @ORM\ManyToMany(targetEntity="ServiceGroup")
* @ORM\JoinTable(
* name="service_servicegroup",
* joinColumns={@ORM\JoinColumn(name="service_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="servicegroup_id", referencedColumnName="id")}
*)
*/
private $groups;
}
E qui fa parte del mio codice sorgente di entità ServiceGroup:
class ServiceGroup
{
/**
* @var ArrayCollection $services
* @ORM\ManyToMany(targetEntity="Service")
* @ORM\JoinTable(
* name="service_servicegroup",
* joinColumns={@ORM\JoinColumn(name="servicegroup_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="service_id", referencedColumnName="id")}
*)
*/
private $services;
}
I utilizzando JoinTable in entrambi i casi, perché questo è il L'unico modo in cui ho trovato che funziona quando si tratta di salvare le relazioni in editor di interfaccia utente, che assomiglia a questo:
Editor di servizio:
redattore Servizio
nome: [Servizio 1]
gruppi ai quali questo servizio fa parte:
[x] Gruppo A
[] Gruppo B
[] Gruppo C
[SAVE]
e redattore ServiceGroup:
editore Gruppo
nome: [Gruppo A]
Servizi appartiene a questo gruppo:
[x] Servizio 1
[] Servizio 2
[] Servizio 3
[SAVE]
Con questa configurazione molti-a-molti sono in grado di utilizzare questi editori (forme) senza problemi, quando utilizzo l'opzione Molti-a-molti senza l'annotazione JoinTable, sono in grado di utilizzare solo un modulo completamente e il secondo non salva le modifiche in "Gruppi a cui appartiene questo servizio" o "I servizi appartengono a questo gruppo" "opzione (dipende da quale direzione sto impostando mapp edBy e inversedBy parametri nell'istruzione di annotazione Many-To-Many).
Il problema che ho è collegato con il meccanismo di generazione dello schema dottrina, quando si cerca di aggiornare lo schema con il comando di Symfony2:
php app/console doctrine:schema:update --dump-sql
sto ottenendo questa eccezione:
[Doctrine\DBAL\Schema\SchemaException]
The table with name 'service_servicegroup' already exists.
Sembra Dottrina cercando di creare una tabella 'service_servicegroup' per ogni istruzione JoinTable.Quindi, sta lavorando allo schema corrente, che ho creato nel database usando lo stesso comando, ma passo dopo passo, quando non è stata definita alcuna relazione Molti-A-Molti e successivamente con una sola definizione di relazione Molti-A-Molti (per entità di servizio). Quando ho aggiunto la relazione Many-To-Many alla seconda entità (ServiceGroup), la mia applicazione sembra funzionare senza problemi dal punto di vista dell'utente, ma non sono più in grado di utilizzare il comando 'doctrine: schema: update' .
Non ho idea di cosa c'è di sbagliato nel mio codice, forse questa relazione dovrebbe essere implementata in modo diverso, o forse è un bug/limitazione di Doctrine. Qualsiasi aiuto o suggerimento sarebbe apprezzato.
UPDATE:
ho notato che quello che mi serve è quello di configurare ManyToMany relazione di avere due lati proprietarie. L'impostazione predefinita è avere un lato proprietario e un lato inverso. Doctrine documentation dice che puoi avere due lati di proprietà in ManyToMany, ma non lo spiega molto. Chiunque può dare un esempio?
SOLUZIONE:
Ho trovato una soluzione alternativa soluzioni, che forse non è l'ideale, ma si sta lavorando per me. Dato che non c'è modo di avere due possidenti in relazione molti a molti, ho modificato l'annotazione di Doctrine per le mie entrate. entità servizio è ora il lato di appartenenza:
class Service
{
/**
* @var ArrayCollection $groups
* @ORM\ManyToMany(targetEntity="ServiceGroup", inversedBy="services", cascade={"all"})
* @ORM\JoinTable(
* name="service_to_group_assoc",
* joinColumns={@ORM\JoinColumn(name="service_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
*)
*/
private $groups;
}
E ServiceGroup entità è lato inverso:
class ServiceGroup
{
/**
* @var ArrayCollection $services
* @ORM\ManyToMany(targetEntity="Service", mappedBy="groups", cascade={"all"})
*/
private $services;
}
Purtroppo, con questa configurazione, relazione viene aggiornata solo quando l'aggiornamento Servizio entità. Quando cambio $ servizi nell'oggetto ServiceGroup e lo mantengo, la relazione rimarrà invariata. Quindi, ho cambiato la mia classe Controller e, con l'aiuto di una soluzione piccola soluzione, ho raggiunto il risultato previsto. Questa è una parte del mio codice di controllo, che è responsabile per l'aggiornamento entità ServiceGroup (con un uso di tipo modulo personalizzato):
// before update - get copy of currently related services:
$services = clone $group->getServices();
// ...
// when $form->isValid() etc. updating the ServiceGroup entity:
// add selected services to group
foreach($group->getServices() as $service)
{
$service->addServiceGroup($group);
$services->removeElement($service);
}
// remove unselected services from group
foreach($services as $service)
{
$service->removeServiceGroup($group);
}
Questo sono implementazioni di addServiceGroup e metodi removeServiceGroup di servizio classe di entità:
/**
* Add group
*
* @param ServiceGroup $groups
*/
public function addServiceGroup(ServiceGroup $groups)
{
if(!in_array($groups, $this->groups->toArray()))
{
$this->groups[] = $groups;
}
}
/**
* Remove group
*
* @param ServiceGroup $groups
*/
public function removeServiceGroup(ServiceGroup $groups)
{
$key = $this->groups->indexOf($groups);
if($key!==FALSE)
{
$this->groups->remove($key);
}
}
Ora ho una relazione molti-a-molti con il lato proprietario (Servizio) e inverso (Gruppo di servizio) e moduli che hanno aggiornato sia l'entità che la relazione durante il salvataggio (il modulo predefinito per l'entità Servizio è sufficiente, ma per ServiceGroup ho fornite le modifiche sopra menzionate). Gli strumenti della console di Symfony/Doctrine funzionano come un incantesimo. Questo probabilmente può essere risolto in modo migliore (più semplice?), Ma per me questo è sufficiente per ora.
funziona se si rilascia - creare lo schema? – jere
No. Ho provato con il database vuoto, l'effetto è identico. Se ho annotazioni JoinTable in entrambe le entità come nell'esempio sopra, doctrine: schema: il comando update non funzionerà. ** Ho notato che ciò di cui ho bisogno è configurare la relazione ManyToMany per avere due lati proprietari **. L'impostazione predefinita è avere un lato proprietario e un lato inverso. [Documentazione] (http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#owning-side-and-inverse-side) dice che puoi avere due possessi in relazione ManyToMany, ma non lo spiega molto. Chiunque può dare un esempio? – Darrarski
Non ho mai avuto davvero fortuna con ManyToMany. Sembra che si imbattano in qualche tipo di problema. Prendi in considerazione la creazione esplicita dell'entità/tabella ServiceServiceGroup e l'impostazione di una relazione OneMo con esso. Non sono sicuro se sarà necessario modificare i moduli o no. Permette inoltre di aggiungere ulteriori attributi all'entità di join. – Cerad