2013-03-27 87 views
0

我有一个表产品,在这些表中的项目表中引用如cart_itemorder_item以及shipping_item删除相关/引用的实体

所有这些提法可选的(product_id在这些表中设置为空)。

我需要有一种方法来删除产品,并仍然保留其他表的记录。我能想到的一种方法是进入所有这些表,将product_id设置为空,然后返回到产品表以删除。但是,因为我可能不知道所有引用产品(许多其他包都可以包含引用该产品的实体)的表,有没有一种方法可以知道所有这些关联以循环并设置为null?

(或者也许还有更好的办法吗?)

PS:这个想法,这是一个购物车,车主可能需要删除过期的产品进行清理,但对于订购,运输的项目,他们仍然需要保持记录。

EDIT1:

这是OrderItem的实体产品参考的定义:

/** 
* @var \Product 
* 
* @ORM\ManyToOne(targetEntity="Product") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="product_id", referencedColumnName="id") 
* }) 
*/ 
private $product; 

我得到的错误:

PDOException:SQLSTATE [23000 ]:完整性约束违规:1451 无法删除或更新父行:外键约束失败 (testorder_item,C ONSTRAINT fk_order_item_product1外键 (product_id)参考文献productid)ON DELETE NO ACTION ON UPDATE NO ACTION)

EDIT2:

我最初设定的onupdate = “SET NULL” 来在order_item实体,并认为这是不够的,它不是:

/** 
* @var \Product 
* 
* @ORM\ManyToOne(targetEntity="Product") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=true, onDelete="SET NULL") 
* }) 
*/ 
private $product; 

在那之后,我公顷d以更新数据库模式。

+1

onDelete =“SET NULL”是去 – Drmjo 2015-02-20 17:55:02

回答

2

假设您在所属实体product与其他实体之间建立了适当的关系,例如cart_item应该有一个foreign_key,你想要的行为是默认的原则2。

看看这里的manual

举个例子,他们表现出User实体的缺失及其相应Comments

$user = $em->find('User', $deleteUserId); 

foreach ($user->getAuthoredComments() AS $comment) { 
    $em->remove($comment); 
} 
$em->remove($user); 
$em->flush(); 

的例子指出:

没有循环在所有创作的评论中,Doctrine只会使用UPDATE语句将外键设置为NULL,并且只有用户才会被删除在flush() - 操作期间从数据库编辑。

这暗示了你的情况,你实际上想要那种行为。所以只要去掉product实体和学说2会自动查找所有其他实体与foreign_key属于该产品,将其设置为NULL

编辑
你的错误信息表明,在试图移除product实体存在的仍然存在foreign_keys,即它们没有被Doctrine正确设置为null。 您需要确保将cascade属性,特别是remove添加到您的实体关系中。它看起来像下面这样:

<?php 
class Product 
{ 
    //... 
    /** 
    * Bidirectional - One-To-Many (INVERSE SIDE) 
    * 
    * @OneToMany(targetEntity="Cart", mappedBy="product", cascade={"remove"}) 
    */ 
    private $carts; 
    //... 
} 
+0

喜Pankrates的方式,感谢指出了这一点,好像那是什么学说文件说。我已经用实体def和我得到的错误更新了我的问题,可否请您看看我是否犯了错误? – mr1031011 2013-03-27 15:06:56

+0

非常感谢您,我不希望它在级联中删除,但您的答案实际上使我走向了正确的方向。好像我必须设置触发器在db中更新set null,我最初将它设置在实体中,并认为这已经足够了。 – mr1031011 2013-03-28 08:23:43

+0

这是这个问题的最强答案... – Drmjo 2015-02-20 17:53:58