2016-05-06 27 views
0

我一直在關注Symfony網站上的How to Embed a Collection of Forms示例。使用嵌入的表單集合保存相關的Doctrine實體時出現Symfony SQL錯誤

我的情況有點不同。我有2個學說實體ExperimentGoalcomposite primary key的關係(見下面的代碼)。

基本上一個Experiment可以有很多Goals,但目標ID只有與Experiment ID和User ID相結合纔是唯一的。

class Goal 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer", options={"default": 1}) 
    * @ORM\Id 
    */ 
    protected $id = 1; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="experiment_id", type="integer", nullable=true, options={"default": null}) 
    * @ORM\Id 
    */ 
    protected $experimentId; 

    /** 
    * @ORM\ManyToOne(targetEntity="Experiment", inversedBy="goals") 
    * @ORM\JoinColumns({ 
    * @ORM\JoinColumn(name="experiment_id", referencedColumnName="id"), 
    * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id") 
    * }) 
    */ 
    protected $experiment; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="user_id", type="integer", nullable=true, options={"default": null}) 
    * @ORM\Id 
    */ 
    protected $userId; 

    /** 
    * @ORM\ManyToOne(targetEntity="Optimcore\UserBundle\Entity\User", inversedBy="goals", cascade={"persist"}) 
    * @ORM\JoinColumn(name="user_id", referencedColumnName="id") 
    */ 
    protected $user; 

    // ... 
} 

我有一個ExperimentType形式嵌入GoalType'collection'形式。

在我的控制器我有以下代碼:

$originalGoals = new ArrayCollection(); 
foreach ($experiment->getGoals() as $goal) { 
    $originalGoals->add($goal); 
} 

$form = $this->createForm(new ExperimentType(), $experiment, array(
    'action' => $this->generateUrl('experiment_goals', array('id' => $experiment->getId())), 
    'method' => 'PUT', 
)); 
$form->handleRequest($request); 

if ($form->isValid()) { 
    $em = $this->getDoctrine()->getManager(); 

    // remove the relationship between the Goal and the Experiment 
    foreach ($originalGoals as $goal) { 
     if (false === $experiment->getGoals()->contains($goal)) { 
      $goal->setExperiment(null); 
      $em->persist($goal); 
      $em->remove($goal); 
     } 
    } 

    foreach ($experiment->getGoals() as $goal) { 
     if (is_null($goal->getUserId())) { 
      $this->getUser()->addGoal($goal); 
      $goal->setUserId($this->getUser()->getId()); 
      $goal->setUser($this->getUser()); 
      $em->persist($goal); 
     } 
    } 

    $em->flush(); 

} 

我的JavaScript的網頁上添加和刪除目標的形式。新目標會分配下一個可用ID,因此如果頁面上的最後一個目標ID爲2,則下一個目標的ID爲3.

添加新目標並保存到數據庫可以正常工作,刪除目標並保存工作正常。

但是,當目標被刪除時,通過頁面上的javascript,然後通過javascript添加新目標,這個目標被分配與刪除目標相同的ID。現在當表單被提交併且Doctrine試圖保存目標時,會拋出一個SQL錯誤,因爲Doctrine嘗試插入一個與Javascript刪除的目標相同的目標,但仍然存在於數據庫中。

在插入新的目標之前,我該如何去取得Doctrine的第一個目標?我試過早些時候沖洗過,但這並沒有幫助。在添加保存新目標前,我如何強制Doctrine刪除舊目標?還是我這樣做都錯了?

這裏的錯誤消息:

An exception occurred while executing 'INSERT INTO goal (id, experiment_id, user_id, name) VALUES (?, ?, ?, ?)' with params ["2", 183, 6, "Goal 2"]: 

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-183-6' for key 'PRIMARY' 

回答

0

一個非常簡單的答案來一個很長的問題是在Doctrine documentation找到。

10.2。原理如何檢測變化

  • 只用一個實體$entityManager->flush($entity)沖洗一個實體。

爲了得到學說來保存新我有$em->remove($goal);後添加$em->flush($goal);之前刪除原來的目標。這將只刷新該單個實體,從數據庫中刪除該記錄。

foreach ($originalGoals as $goal) { 
    if (false === $experiment->getGoals()->contains($goal)) { 
     $goal->setExperiment(null); 
     $em->persist($goal); 
     $em->remove($goal); 

     // commit this change to the database 
     $em->flush($goal); 
    } 
} 
相關問題