咨询symfony中的实体关系(学说)

时间:2016-07-30 12:40:42

标签: doctrine-orm doctrine symfony symfony-2.1

我会具体。 我有实体任务,城市和组织者。 当我尝试删除组织者时,会出现与任务错误的关系

  

执行'DELETE FROM Organizer WHERE id时发生异常   =?'与params [522]:

     

SQLSTATE [23000]:完整性约束违规:1451无法删除或   更新父行:外键约束失败(testQuest,   约束FK_82D6D713876C4DDA外键(organizer_id)   参考Organizerid))

我对正确配置关系的方式感到困惑。 逻辑是:

  1. 我们添加新城市。
  2. 我们添加新的组织者并将城市纳入组织者。
  3. 我们创造新的任务,而不是将城市和组织者纳入其中。
  4. 如果我们删除组织者 - 任务中的组织者ID必须是 删除(不得删除任务)。
  5. 如果我们删除组织者 - 必须删除城市中的组织者ID (也不能删除城市)。
  6. 我很抱歉我的愚蠢描述,但我试图排除误解。

    那么,我应该根据自己的情况使用什么是正确的实体关系?

    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();
            }
        }
    

3 个答案:

答案 0 :(得分:2)

问题很简单,您无法删除组织者,因为现有的Quest会引用它。在您的情况下,您必须首先删除关系。我不知道使用doctrine自动执行此操作的方法,但您可以在preRemove事件中配置事件侦听器,并使Quest管理器字段为null。我不确定事件监听器是否在symfony 2.1中实现,但我希望如此。您还可以选择在删除调用之前直接在控制器中执行关系null。同样的情况适用于城市。查看此文档链接:

How to Register Event Listeners and Subscribers

Doctrine Lifecycle Events

希望这对你有所帮助。

答案 1 :(得分:1)

您必须配置Doctrine或DB以将关系设置为null。

  • 使用doctrine,只需删除您的实体:

    $em=$this->getDoctrine()->getEntityManager(); // or getManager() in current Doctrine versions.
    $em->remove($organizer);
    $em->flush();
    
  • 使用您的数据库:

    更改JoinColumn注释:

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

    使用第二种方法,您将能够使用DQL查询。 这种方法绕过了学说,第一种是首选。

答案 2 :(得分:1)

我忘记了两件重要的事情。

  1. Doctrine Lifecyle Events
  2. php bin / console doctrine:generate:entities AppBundle / Entity / Quest将只生成常用方法。 (有 没有removeOrganizer()函数)
  3. 所以,解决方案很简单,但是......见下文。

    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);
            }
        }
    }
    

    如您所见,我为Quest Entity添加了新功能removeOrganizer和removeCity,并将其与City and Organizer Entity中的事件preRemove一起使用。

    PS我相信有更好的解决这样的任务的做法。所以,我愿意批评你。