2013-09-28 11 views
8

Mam problem z jednokierunkową relacją ManyToMany w Doctrine. Sprawa jest bardzo prosta: produkt ma wiele tagów. Tag może być dołączony do Produktu, ale także do dowolnej jednostki "taggable" w moim modelu. Oto fragment kodu:Doctrine ManyToMany: usuwanie obiektu

/** 
* @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; 

} 

Od tego momentu kod jednokierunkowy relacja klasy Tag jest pomijany.

Dla takiego związku zdefiniowanego Nauki generowane następujący kod SQL (SQL dla tabel oraz znaczniki tabeli produktów jest pomijany):

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 | 

ja chce usunąć produkt, który posiada kilka znaczników przyłączonych do niego.

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

To oczywiście nie ze względu na integralność naruszenia ograniczenia ("Nie można usunąć lub zaktualizować wiersz nadrzędny: a ograniczenie klucza obcego nie powiedzie się (products_tags, CONSTRAINT FK_E3AB5A2CBAD26311 FOREIGN KEY (tag_id) odniesienia tags (id))"").

Gdy zmieniam tabelę products_tags dodając opcję NA KASK DELEGE na klucze obce, działa ona tak, jak chcę. Mogę ŁATWO usunąć TAG ($ em-> remove ($ tag)) i PRODUCT ($ em-> remove ($ product), który automatycznie usuwa wiersze z odniesieniami z tabeli products_tags

Jak mój kod powinien wyglądać, aby uzyskać product_tags table with ON CASCADE DELETE klucze obce? Już zmęczyłem się kaskadą = {"wszystko"} ale nie udało się

Wiem, mogę usunąć cały tag z kolekcji tagów produktu, ale jak już wspomniałem, chciałbym go osiągnąć w jednym etapie, po prostu dzwoniąc do usunięcia metody obiektu menedżera podmiot.

Does Doktryna naprawdę brak takiego?

Odpowiedz

22

Ok, Udało mi się zagłębić w doctrine2 docs;) Rozwiązanie polega na dodaniu onDelete = "kaskada" do @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; 

} 

zauważyć, że kaskada = { „wszystko”} jest zarządzany na poziomie obiektu (w aplikacji), natomiast onDelete = „Kaskada” jest na poziomie bazy danych.