2016-07-30 81 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