我有一个表产品,这些表中的项目在 cart_item 和 order_item 等表格中引用,以及 shipping_item 等。
所有这些引用都是可选的(product_id在这些表中设置为可为空)。
我需要有办法删除产品并保留其他表的记录。我能想到的一种方法是进入所有这些表,将product_id设置为null,然后返回产品表进行删除。但是,由于我可能不知道引用产品的所有表(许多其他捆绑包可以包含引用此产品的实体),是否有一种方法可以让我知道所有这些关联到循环通过并设置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 无法删除或更新父行:外键约束失败 (
test
。order_item
,C ONSTRAINTfk_order_item_product1
外键 (product_id
)引用product
(id
)ON DELETE NO ACTION ON 更新无行动)
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;
之后,我还必须更新数据库模式。
答案 0 :(得分:3)
假设您在拥有实体product
与其他实体之间建立了正确的关系,例如cart_item
应该有一个foreign_key,你想要的行为是doctrine 2的默认行为。
作为示例,他们会显示删除User
实体及其对应的Comments
$user = $em->find('User', $deleteUserId);
foreach ($user->getAuthoredComments() AS $comment) {
$em->remove($comment);
}
$em->remove($user);
$em->flush();
示例说明:
没有循环遍历所有创作的注释,Doctrine只会使用UPDATE语句将外键设置为NULL,并且在flush() - Operation期间只会从数据库中删除User。
这告诉我,在您的情况下,您实际上想要这种行为。因此,只需删除product
实体,并且doctrine 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;
//...
}