首页 文章

Doctrine ManyToMany:删除一个对象

提问于
浏览
9

我在Doctrine中遇到单向ManyToMany关系的问题 . 案例非常简单:产品有很多标签 . 标签可以附加到Product,也可以附加到模型中的任何“可标记”实体 . 这是我的代码片段:

/**
 * @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类的单向关系代码 .

对于这样定义的关联,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 ,CONSTRAINT FK_E3AB5A2CBAD26311 FOREIGN KEY( tag_id )REFERENCES tagsid ))'”) .

当我改变products_tags表时,将ON DELETE CASCADE添加到外键,它可以正常工作 . 我可以轻松删除TAG($ em-> remove($ tag))和PRODUCT($ em-> remove($ product),它们会自动从products_tags表中删除引用的行 .

我的代码应该如何使用ON CASCADE DELETE外键获取products_tags表?我已经厌倦了cascade = {“all”}但它失败了 .

我知道,我可以从产品的标签集合中删除所有标签,但正如我所提到的,我想通过调用实体管理器对象的remove方法一步完成它 .

Doctrine真的缺乏这个吗?

1 回答

  • 25

    好吧,我通过挖掘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;
    
    }
    

    请注意,cascade = {“all”}在对象级别(在您的应用程序中)管理,而onDelete =“cascade”在数据库级别 .

相关问题