Home > Software design >  Looping through entities and updating them causes error on flush
Looping through entities and updating them causes error on flush

Time:02-26

I am new to symfony and doctrine. And I am compeleting a code that someone else has started. I mainly have a form for which I wrote a validation function in my controller. In this form a BusReservation object along with its BusReservationDetails are created and saved to the db. so at the end of the form validation function, after the entities are saved in DB, I call a BusReservation Manager method which is transformBusReservationDetailIntoBusTicket which aim is to take each BusReservationDetail in the BusReservation oject and create a a new entity BusTicket based on it.

so I created this loop (please let me know if there is something wrong in my code so that i can write in a good syntax). I tried to put the 3 persist that you see at the end of the code but I got : Notice: Undefined index: 0000000.. I tried to merge (the last 3 lines in code ) I got the following :

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"}).

I got this same error when i commented all theh 6 lines of merge and flush.

PS: I am not expecting the flush to fully work. There are some properties that are nullable=false so I assume that I must set them as well so that the entities can be saved to DB. But the error i got is by far different than this.

PS : I noticed that there is a onFlush where the customInfo is updated and persisted again and other things happen, but i am trying to debug step by step. I tried to detach this event but still got the same errors. so I want to fix my code and make sure that the code part that i wrote in the manager is correct and if that's the case then I can move to debugging the event Listener. so please I would like to know if the following code is correct and why the flush is not working.


    /**
     * @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;

CodePudding user response:

The answer is in your error message. You either have to add cascade={"persist"} to your entity annotation, or explicitly call persist. I don't believe you need em->merge() in this situation as you're never taking the entities out of context.

Where you have all your persist lines commented out, just try putting this in

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

and if you're looping through a ton of entities, you could try adding the flush inside the loop at the end instead of a huge flush at the end.

  • Related