遍历实体并更新它们会导致刷新错误

Looping through entities and updating them causes error on flush

我是 symfony 和 doctrine 的新手。我正在完成别人已经开始的代码。我主要有一个表单,我在控制器中为其编写了一个验证函数。在这种形式下,一个 BusReservation 对象及其 BusReservationDetails 被创建并保存到数据库中。所以在表单验证函数的最后,在实体保存在数据库中之后,我调用了一个 BusReservation 管理器方法,它是 transformBusReservationDetailIntoBusTicket 其目的是获取 BusReservation 对象中的每个 BusReservationDetail 并基于它创建一个新的实体 BusTicket。

所以我创建了这个循环(请让我知道我的代码是否有问题,以便我可以用良好的语法编写)。我试着把你在代码末尾看到的 3 持久化,但我得到了:注意:未定义的索引:0000000.. 我尝试合并(代码中的最后 3 行)我得到以下结果:

A new entity was found through the relationship 'MyBundle\Entity\CustomInfo#busTicket' that was not configured to cascade persist operations for entity: . To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).

当我评论所有 6 行合并和刷新时,我遇到了同样的错误。

PS:我不希望冲洗能完全起作用。有一些属性是 nullable=false,所以我假设我也必须设置它们,以便实体可以保存到数据库中。但是我得到的错误与此大不相同。

PS :我注意到有一个 onFlush,其中 customInfo 被更新并再次持久化并且发生了其他事情,但我正在尝试逐步调试。我试图分离此事件,但仍然出现相同的错误。所以我想修复我的代码并确保我在管理器中编写的代码部分是正确的,如果是这样的话,我可以继续调试事件监听器。所以我想知道以下代码是否正确以及为什么冲洗不起作用。


    /**
     * @param $idBusReservation
     * @return bool
     * @throws \Doctrine\ORM\NonUniqueResultException
     */
    public function transformBusReservationIntoBusTicket($idBusReservation): bool
    {   $result = "into the function";
        /** @var BusReservation $busReservation */
        $busReservation = $this->em->getRepository('MyBundle:BusReservation')->find($idBusReservation);
        if ($busReservation !== null) {
            /** @var BusReservationDetail $busReservationDetail */
            foreach ($busReservation->getBusReservationDetails() as $busReservationDetail) {
                $busTicket = new BusTicket($busReservationDetail->getBusModel(), $busReservation->getPassenger());
                $busReservationDetail->setBusTicket($busTicket);
                $busTicket->setBusReservationDetail($busReservationDetail);
                $busTicket->setOwner($busreservation->getPassenger()->getName());
                if ($busReservationDetail->getBusModel()->getCode() === 'VIPbus') {
                 //  perform some logic .. later on
                } else {
                    $customInfo = new CustomInfo();
                    $customInfo->setNumber(1551998);
                    // $customInfo->setCurrentMode(
                    //     $this->em->getRepository('MyBundle:Mode')
                    //         ->find(['code' => 'Working'])
                    // );
                    $customInfo->setBusTicket($busTicket);
                    // Bus ticket :
                    $busTicket->addCustomInfo($customInfo);
                    $busTicket->setComment($busReservation->getComment());
                }

                /** @var Mode $currentMode */
                $currentMode = $this->em->getRepository('MyBundle:Mode')
                                    ->findOneBy(['code' => 'Working']);
                $busTicket->setCurrentMode($currentMode);
                // $this->em->merge($customInfo);
                // $this->em->merge($busReservationDetail);
                // $this->em->merge($busTicket);
                // $this->em->persist($customInfo); 
                // $this->em->persist($busReservationDetail); 
                // $this->em->persist($busTicket); 
            }
           
            $this->em->flush();
          //  $this->em->clear();
        }
        return $result;
    }
// *************** In BusReservation.php ********************

   /**
     * @ORM\OneToMany(targetEntity="MyBundle\Entity\BusReservationDetail", mappedBy="busReservation")
     */
    private $busReservationDetails;

    /**
     * Get busReservationDetails
     * 
     *@return Collection
     */
    public function getBusReservationDetails()
    {
        return $this->busReservationDetails;
    }

// ---------------------------------------------------------------------
// *************** In BusReservationDetail.php ********************


    /**
     * @ORM\ManyToOne(targetEntity="MyBundle\Entity\BusReservation", inversedBy="busReservationDetails")
     * @ORM\JoinColumn(name="id_bus_reservation", referencedColumnName="id_bus_reservation", nullable=false)
     */
    private $busReservation;

    /**
     * @ORM\ManyToOne(targetEntity="MyBundle\Entity\BusModel")
     * @ORM\JoinColumn(name="bus_model_code", referencedColumnName="bus_model_code", nullable=false)
     */
    private $busModel;

    /**
     * @ORM\OneToOne(targetEntity="MyBundle\Entity\BusTicket", inversedBy="busReservationDetail", cascade={"merge","remove","persist"})
     * @ORM\JoinColumn(name="id_bus_ticket", referencedColumnName="id_bus_ticket")
     */
    private $busTicket;

    /**
     * @return BusModel
     */
    public function getBusModel()
    {
        return $this->busModel;
    }
//-------------------------------------------------------------------------
// ************ IN BusTicket.php *****************************

   /**
    * @ORM\OneToMany(targetEntity="MyBundle\Entity\CustomInfo", mappedBy="busTicket")
    */
    private $customInfos;


 /**
    *
    * @param  CustomInfo  $customInfo
    *
    * @return BusTicket
    */
    public function addCustomInfot(CustomInfo $customInfo)
    {
       if (!$this->customInfos->contains($customInfo)) {
          $this->customInfos[] = $customInfo;
       }
 
       return $this;
    }

    /**
    * @ORM\OneToOne(targetEntity="MyBundle\Entity\busReservationDetail", mappedBy="busTicket")
    */
   private $busReservationDetail;

// --------------------------------------------------------------------
   //   CUSTOMINFO ENTITY
   /**
    * @ORM\ManyToOne(targetEntity="MyBundle\Entity\BusTicket", inversedBy="customInfos")
    * @ORM\JoinColumn(name="id_bus_ticket", referencedColumnName="id_bus_ticket", nullable=false)
    */
    private $busTicket;

答案在您的错误消息中。您要么必须将 cascade={"persist"} 添加到您的实体注释,要么显式调用 persist。我认为在这种情况下您不需要 em->merge() ,因为您永远不会将实体脱离上下文。

在所有持久行都被注释掉的地方,只需尝试将其放入

$this->em->persist($busTicket); 
$this->em->persist($busReservationDetail); 
$this->em->persist($customInfo); 

如果您要遍历大量实体,您可以尝试在循环的末尾添加刷新,而不是在最后添加大量刷新。