2016-07-30 82 views
1

我會特定的。 我有實體任務,城市和組織者。 當我嘗試刪除組織者,具有與追求錯誤的關係出現關於symfony中的實體關係的諮詢(學說)

發生異常而執行「DELETE FROM WHERE主辦ID =?使用參數[522]:

SQLSTATE [23000]:完整性約束違規:1451不能刪除或 更新父行:外鍵約束失敗(testQuest, 約束FK_82D6D713876C4DDA外鍵(organizer_id) 參考Organizerid))

我對配置關係的正確方式完全混淆。 邏輯是:

  1. 我們添加新城市。
  2. 我們添加新的組織者,並把城市放入組織者。
  3. 我們創造新的追求,並將城市和組織者放入其中。
  4. 如果我們刪除管理器 - 任務中的組織者ID必須是 刪除(任務不得刪除)。
  5. 如果我們刪除了組織者 - 而且城市中的組織者ID也必須刪除 (城市也不能刪除)。

我很抱歉我非常愚蠢的描述,但我試圖排除誤解。

那麼,我應該爲我的情況使用什麼樣的正確的實體關係?

class Quest { 
    ... 
    /** 
    * @ORM\JoinColumn(name="organizer_id", referencedColumnName="id") 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Organizer") 
    */ 
    protected $organizer;  
} 

class Organizer { 
    ... 
    /** 
    * @ORM\Column(type="string", length=140) 
    */ 
    protected $name; 

    /** 
    * @ORM\ManyToMany(targetEntity="AppBundle\Entity\City", inversedBy="organizers") 
    * @ORM\JoinTable(name="organizers_cities") 
    */ 
    protected $cities; 

    public function __construct() { 
     $this->quests = new ArrayCollection(); // i don't remember why this is here 
    } 
} 

class City { 

     /** 
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Organizer", mappedBy="cities") 
     */ 
     protected $organizers; 
     /** 
     * Constructor 
     */ 
     public function __construct() { 
      $this->quests = new \Doctrine\Common\Collections\ArrayCollection(); 
      $this->organizers = new \Doctrine\Common\Collections\ArrayCollection(); 
     } 
    } 

回答

1

我忘了2件重要的事情。

  1. 主義生命週期活動
  2. PHP斌/控制檯學說:生成:實體 的appbundle /實體/任務將產生唯一的共同方法。 (有 沒有removeOrganizer()函數)

所以,解決方案很簡單,但...見下文。

class Quest { 
    ... 
    /** 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Organizer", inversedBy="quests") 
    * @ORM\JoinColumn(name="organizer_id", referencedColumnName="id") 
    */ 
    protected $organizer; 

    ... 
    public function removeOrganizer() 
    { 
     $this->organizer = null; 
     return $this; 
    } 
    public function removeCity() 
    { 
     $this->city = null; 
     return $this; 
    } 
} 
class Organizer { 
    ... 
    /** 
    * @ORM\ManyToMany(targetEntity="AppBundle\Entity\City", inversedBy="organizers") 
    */ 
    protected $cities; 
    /** 
    * @ORM\OneToMany(targetEntity="AppBundle\Entity\Quest", mappedBy="organizer")) 
    */ 
    protected $quests; 

    public function __construct() { 
     $this->quests = new ArrayCollection(); 
    } 
    ... 
    /** 
    * @ORM\PreRemove() 
    */ 
    public function removeRelationWithQuests() { 
     foreach($this->getQuests() as $quest) { 
      $quest->removeOrganizer() 
        ->setStatus(0); 
     } 
    } 
} 
class City { 
    ... 
    /** 
    * @OneToMany(targetEntity="AppBundle\Entity\Quest", mappedBy="city")) 
    */ 
    protected $quests; 
    /** 
    * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Organizer", mappedBy="cities") 
    */ 
    protected $organizers; 
    ... 
    /** 
    * @ORM\PreRemove() 
    */ 
    public function removeRelationWithQuests() { 
     foreach($this->getQuests() as $quest) { 
      $quest->removeCity() 
        ->setStatus(0); 
     } 
    } 
} 

正如你可以看到我添加了新的功能removeOrganizer和removeCity探祕實體,在市和組織者實體與事件刪除前使用它。

PS我相信有更好的解決這類問題的做法。所以,我對你的批評是開放的。

2

問題很簡單,你不能刪除組織者,因爲被現有的Quest引用。在你的情況下,你必須先刪除關係。我不知道如何使用doctrine自動執行此操作,但可以在preRemove事件中配置事件偵聽器,並將Quest organizer字段設置爲空。我不確定事件監聽器是否在symfony 2.1中實現,但我希望。您也可以選擇在刪除調用之前直接在控制器中執行關係null。同樣的情況適用於城市。選中此單證鏈接:

How to Register Event Listeners and Subscribers

Doctrine Lifecycle Events

希望這有助於你。

1

您必須配置Doctrine或您的數據庫以將關係設置爲null。

  • 教義,只是刪除你的實體,以便:

    $em=$this->getDoctrine()->getEntityManager(); // or getManager() in current Doctrine versions. 
    $em->remove($organizer); 
    $em->flush(); 
    
  • 有了您的DB:

    更改JoinColumn註解:

    class Quest { 
        ... 
        /** 
        * @ORM\JoinColumn(nullable=false, onDelete="SET NULL",name="organizer_id", referencedColumnName="id") 
        * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Organizer") 
        */ 
        protected $organizer;  
    } 
    

    採用第二種方法,你會能夠使用您的DQL查詢。 此方法繞過原則,第一個是首選。

+1

他不想在級聯中刪除Quest,只是將關係設爲null,你確定這是你的代碼在做什麼? – abdiel

+0

哦,好吧,不明白。我重寫了答案。謝謝。 – Alsatian