2013-09-28 3 views
8

У меня проблема с однонаправленными отношениями ManyToMany в Доктрине. Случай очень прост: в продукте много тэгов. Тег может быть прикреплен к Продукту, но также и к любому «taggable» объекту в моей модели. Вот фрагмент моего кода:Doctrine ManyToMany: удаление объекта

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

} 

Так как его однонаправленное отношение код класса Tag опущено.

Для такой Defined ассоциации Doctrine генерируется следующий SQL кода (SQL для продуктов таблицы и теги таблицы пропущено):

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 | 

Я хотел бы, чтобы удалить продукт, который имеет некоторые теги, присоединенные к нему.

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

Это явно не удается из-за целостностью нарушения ограничений («Невозможно удалить или обновить родительскую строку: ограничение внешнего ключа не удается (products_tags, скованность FK_E3AB5A2CBAD26311 FOREIGN KEY (tag_id) Лит tags (id))»).

Когда я изменяю таблицу products_tags, добавляя ON DELETE CASCADE к внешним ключам, он работает так, как я хочу. Я могу легко удалить TAG ($ em-> remove ($ tag)) и PRODUCT ($ em-> remove ($ product), который автоматически удаляет ссылочные строки из таблицы products_tags.

Как мой код должен выглядеть как получить products_tags table with ON CASCADE DELETE внешние ключи? Я уже устал от cascade = {"all"}, но это не получилось.

Я знаю, я могу удалить все теги из коллекции тегов продукта, но, как я уже говорил, хотел бы достичь его в один шаг, просто позвонив по телефону удалить метод объекта управляющего объектом.

ли доктрина действительно не хватает этого?

ответ

22

Ok, Я сумел, копаясь в Doctrine2 docs;) Решение состоит в том, чтобы добавить onDelete = "cascade" - @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; 

} 

Заметим, что каскадно = { «все»} управляется на уровне объекта (в приложении), в то время как OnDelete = «Каскад» находится на уровне базы данных.

Смежные вопросы