2013-09-28 78 views
8

我有单向ManyToMany关系在教义中的问题。案例非常简单:产品有很多标签。标签可以附加到产品,也可以附加到我的模型中的任何“标签”实体。这里是我的代码片段:学说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类的单向关系代码被省略。

对于这样定义的关联学说生成以下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外键(tag_id)参考文献tagsid))“”)。

当我改变products_tags表添加ON DELETE CASCADE到外键它工作正如我想。我可以很容易地删除TAG($ em-> remove($ tag))和PRODUCT($ em-> remove($ product),它们可以自动从products_tags表中删除引用行。

我的代码应该如何获得products_tags我已经厌倦了cascade = {“all”}但它失败了。

我知道,我可以从产品的标记集合中删除所有标记,但正如我所提到的,我想要实现这一步,只是通过调用删除实体管理对象的方法。

是否真的学说缺乏呢?

回答

22

好,我通过挖掘Doctrine2文档来管理自己;)解决方案是将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 =“级联”是在数据库级别。