2013-03-27 78 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