2013-09-28 23 views
8

Ho avuto problemi con la relazione ManyToMany unidirezionale in Doctrine. Il caso è molto semplice: il prodotto ha molti tag. Il tag può essere associato al Prodotto ma anche a qualsiasi entità "taggable" nel mio modello. Ecco uno snippet del mio codice:Doctrine ManyToMany: rimozione di un oggetto

/** 
* @Entity 
* @Table(name="products") 
**/ 
class Product { 

    /** some other fields here */ 

    /** 
    * @ManyToMany(targetEntity="Tag") 
    * @JoinTable(name="products_tags", 
    *  joinColumns={@JoinColumn(name="product_id", referencedColumnName="id")}, 
    *  inverseJoinColumns={@JoinColumn(name="tag_id", referencedColumnName="id")}  
    *  ) 
    */ 
    protected $tags; 

} 

Poiché il suo codice di relazione unidirezionale della classe Tag è omesso.

Per tale associazione definito dottrina generato il seguente codice SQL (SQL per tavola e tag prodotti tabella viene saltata):

CREATE TABLE `products_tags` (
    `product_id` int(11) NOT NULL, 
    `tag_id` int(11) NOT NULL, 
    PRIMARY KEY (`product_id`,`tag_id`), 
    KEY `IDX_E3AB5A2C4584665A` (`product_id`), 
    KEY `IDX_E3AB5A2CBAD26311` (`tag_id`), 
    CONSTRAINT `FK_E3AB5A2CBAD26311` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`), 
    CONSTRAINT `FK_E3AB5A2C4584665A` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci | 

desidero rimuovere il prodotto che ha alcune modifiche allegate ad esso.

/* $product is already persisted, $em is an Entity Manager */ 
$em->remove($product); 
$em->flush(); 

Non riesce evidentemente a causa di violazione del vincolo di integrità ("Impossibile eliminare o aggiornare una riga padre: un vincolo di chiave esterna non riesce (products_tags, VINCOLO FK_E3AB5A2CBAD26311 FOREIGN KEY (tag_id) Riferimenti tags (id)) '").

Quando altero la tabella products_tags aggiungendo ON DELETE CASCADE a chiavi esterne funziona come voglio. Posso FACILMENTE rimuovere TAG ($ em-> remove ($ tag)) che rimuove automaticamente le righe di riferimento dalla tabella products_tags

Come dovrebbe apparire il mio codice per ottenere products_tags tabella con ON CASCADE DELETE chiavi esterne? Sono già stanco con cascade = {"all"} ma non è riuscito.

Lo so, posso rimuovere tutti i tag dalla raccolta di tag del prodotto, ma come ho detto vorrei realizzarla in un unico passaggio, semplicemente chiamando il metodo rimuovere entità gestore oggetti.

fa Dottrina davvero mancanza di quella?

risposta

22

Ok, Sono riuscito a scavare nei documenti Doctrine2;) La soluzione è aggiungere onDelete = "cascade" a @JoinColumn.

/** 
* @Entity 
* @Table(name="products") 
**/ 
class Product { 

    /** some other fileds here */ 

    /** 
    * @ManyToMany(targetEntity="Tag") 
    * @JoinTable(name="products_tags", 
    *  joinColumns={@JoinColumn(name="product_id", referencedColumnName="id", onDelete="cascade")}, 
    *  inverseJoinColumns={@JoinColumn(name="tag_id", referencedColumnName="id", onDelete="cascade")}  
    *  ) 
    */ 
    protected $tags; 

} 

Si noti che, a cascata = { "tutto"} è gestito a livello di oggetto (nel vostro app), mentre onDelete = "a cascata" è a livello di database.