如何在没有级联选项的情况下从反向MTO关系侧移除欠侧?,如何更新关系的反向侧?

时间:2017-07-25 08:46:09

标签: doctrine-orm sql-update one-to-many many-to-one bidirectional-relation

如果没有级联选项,如何从反转的MTO关系侧移除欠侧? ,如何在没有级联选项的情况下更新关系的反面?

错误是,如果我更改房间(MTO)的地址(OTM),房间仍保留在以前的地址,虽然我将其删除。

if( $this->addrOTM_b_ -> getRoomMTO_b_1() -> contains($this) ) {
    $this->addrOTM_b_ -> getRoomMTO_b_1() -> remove($this); 
} 

如果我检查房间的地址 - 这是正确的新地址。 但是,如果我检查地址中的房间,他们是错的,因为存在的房间已被删除。

也许有一个命令如何冲洗实体?或者命令如何从地址中删除房间?或者也许不可能在实体级别上进行,并且我将在Controller操作级别上进行此操作?

这篇文章的内容是:Doctrine: can't removeElement from inverse side of the relation

这只是关于双向MTO关系的说明, 通常很难将房间转移到另一个地址,除非它是船/帐篷/面包车。

P.S。 我知道在foreach循环内部冲洗是不好的, 但我无法清除实体管理器,因为我将在第二个循环中使用实体。 无论如何,这些循环是轻微的,只有5个地址和20个房间。

//控制器动作,夹具类型

 //FIRST ROUND seeting random address for each room
    foreach ( $roomEntArr as $roomEnt ) { 
        $addrCnt = count($addrEntArr)-1; 
        $i = rand(0, $addrCnt); 
        $addrEnt = $addrEntArr[$i];
        $roomEnt->setAddrOTM_b_($addrEnt);
        $this->em->persist($roomEnt);
        $this->em->persist($addrEnt);  
        $this->em->flush();
    }

    $addrRoomArr1 = [];  
    foreach ( $addrEntArr as $ent1 ) {    
        $addrId = $ent1->getId();
        $roomEnts = $ent1->getRoomMTO_b_1(); $roomStr="";
        if( !empty($roomEnts) ) {
            foreach ($roomEnts as $addr) { $roomStr .= $addr->getId().',';  }
        }
        $addrRoomArr1[$addrId] = $roomStr; 
    } //foreach ( $ent1arr as $ent1 ) { 

    $roomAddrArr1 = [];
    if( $dir==='b' ) {
        foreach ( $roomEntArr as $ent2 ) {   
            $roomId = $ent2->getId(); 
            $addr = $ent2->getAddrOTM_b_(); $addrStr="";
            if($addr !== null) { $addrStr = $addr->getId().','; }
            $roomAddrArr1[$roomId] = $addrStr; 
        } //foreach ( $ent1arr as $ent1 ) { 
    } //if( $dir==='b' ) {

    //SECOND ROUND seeting random address for each room
    foreach ( $roomEntArr as $roomEnt ) { 
        $addrCnt = count($addrEntArr)-1; 
        $i = rand(0, $addrCnt); 
        $addrEnt = $addrEntArr[$i];
        $roomEnt->setAddrOTM_b_($addrEnt);
        $this->em->persist($roomEnt);
        $this->em->persist($addrEnt);  
        $this->em->flush();
    }

    $addrRoomArr1 = [];  
    foreach ( $addrEntArr as $ent1 ) {    
        $addrId = $ent1->getId();
        $roomEnts = $ent1->getRoomMTO_b_1(); $roomStr="";
        if( !empty($roomEnts) ) {
            foreach ($roomEnts as $addr) { $roomStr .= $addr->getId().',';  }
        }
        $addrRoomArr1[$addrId] = $roomStr; 
    } //foreach ( $ent1arr as $ent1 ) { 

    $roomAddrArr1 = [];
    if( $dir==='b' ) {
        foreach ( $roomEntArr as $ent2 ) {   
            $roomId = $ent2->getId(); 
            $addr = $ent2->getAddrOTM_b_(); $addrStr="";
            if($addr !== null) { $addrStr = $addr->getId().','; }
            $roomAddrArr1[$roomId] = $addrStr; 
        } //foreach ( $ent1arr as $ent1 ) { 
    } //if( $dir==='b' ) {

//房间实体

<?php

namespace DctrBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\Index;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\OneToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\ManyToMany;
use DctrBundle\Entity\AddrOTM_b_;


/** 
/** 
 * @Table(name="t_roomMTO_b_1")
 * @Entity( repositoryClass="DctrBundle\Repository\RoomMTO_b_1Repository" )
 */ 
class RoomMTO_b_1 {

    /**
     * @var integer
     *
     * @Column(name="id", type="integer" )
     * @Id
     * @GeneratedValue(strategy="AUTO")
     */
    private $id;

/**
 * @ManyToOne(targetEntity="DctrBundle\Entity\AddrOTM_b_", inversedBy="roomMTO_b_1" )
 * @JoinColumn(name="addr_id", referencedColumnName="id")
 */
    private $addrOTM_b_; 


    public function __construct() { 
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }                     


    /**
     * Get AddrOTM_b_
     *
     * @return DctrBundle\Entity\AddrOTM_b_
     */
    public function getAddrOTM_b_()
    {
        return $this->addrOTM_b_;
    }

   /**  
     * Get AddrOTM_b_
     *
     * @return DctrBundle\Entity\AddrOTM_b_
     */
    public function setAddrOTM_b_( $addrOTM_b_ )  
   {
        if ( $addrOTM_b_ !== null ) {

//if current address is not null, and if it is not the same
//1) remove the room from the previous address if it exists
//2) set new address to this room ( automatically removes the oldAddress from the room)
            if ( $this->addrOTM_b_ !== null ) {

                if( $addrOTM_b_->getId() != $this->addrOTM_b_->getId() ) {

                    // first you have to remove this room from previous address - this part does not work, according docs : Changes made only to the inverse side of an association are ignored. Make sure to update both sides of a bidirectional association (or at least the owning side, from Doctrine’s point of view). http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html
                    if( $this->addrOTM_b_ -> getRoomMTO_b_1() -> contains($this) ) {
                        $this->addrOTM_b_ -> getRoomMTO_b_1() -> remove($this); 
                    } 
                    // then you can set the room to the new address   
                     $this->addrOTM_b_ = $addrOTM_b_; 
                } // if( $addrOTM_b_->getId() != $this->addrOTM_b_->getId ) {  

            } // if ( $this->addrOTM_b_ !== null ) {   
            else {
                //if current address is null, just set the address
                $this->addrOTM_b_ = $addrOTM_b_; 
            } 

            //3) add room to the new address
            if ( !$addrOTM_b_->hasRoomMTO_b_1($this) ) { 
                //$addrMTM_b_1->getRoomMTM_b_()->removeElement($this); 
                $addrOTM_b_->addRoomMTO_b_1($this); 
            }
            return $this; 
        } // if ( $addrOTM_b_ !== null ) {

        else {
            if ( $this->addrOTM_b_ !== null ) {
                $idold = $this->addrOTM_b_->getId();
                //remove this room from previous address
                if( $this->addrOTM_b_ -> getRoomMTO_b_1() -> contains($this) ) {
                    $this->addrOTM_b_ ->getRoomMTO_b_1()->remove($this);
                }
                $this->addrOTM_b_ = null; 
            } // if ( $this->addrOTM_b_ !== null ) {
            return true; 
        } // else of if ( $addrOTM_b_ !== null ) {            

    } //public function setAddrOTM_b_( $addrOTM_b_ )  

    /** 
     * @param DctrBundle\Entity\RoomMTO_b_1 $AddrOTM_b_
     * @return bool  
     */
    public function hasAddrOTM_b_($addrOTM_b_)
    {  
        if( ($addrOTM_b_!==null) && ($this->addrOTM_b_!== null) ) {
            return ( $addrOTM_b_->getId() == $this->getAddrOTM_b_()->getId() );
        }
        else {
            return false;
        }
    }   



    /**
     * Return Entity as string  
     * 
     * @return string String representation of this class
     */
    public function __toString()
    {
        return strval($this->id);
    }

 } // class RoomMTO_b_1 {

//地址实体

<?php

namespace DctrBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\Index;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\OneToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\ManyToMany;
use DctrBundle\Entity\RoomMTO_b_1;


/** 
/** 
 * @Table(name="t_addrOTM_b_")
 * @Entity( repositoryClass="DctrBundle\Repository\AddrOTM_b_Repository" )
 */ 
class AddrOTM_b_ {

    /**
     * @var integer
     *
     * @Column(name="id", type="integer" )
     * @Id
     * @GeneratedValue(strategy="AUTO")
     */
    private $id; 

/**
 * @OneToMany(targetEntity="DctrBundle\Entity\RoomMTO_b_1", mappedBy="addrOTM_b_" )
 */
     private $roomMTO_b_1; 


    public function __construct() { 
        $this->roomMTO_b_1 = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }                     

    /**
     * Get RoomMTO_b_1
     *
     * @return DctrBundle\Entity\RoomMTO_b_1
     */
    public function getRoomMTO_b_1()
    {
        return $this->roomMTO_b_1;
    }

    /**
     * Remove RoomMTO_b_1
     *
     * @param DctrBundle\Entity\AddrOTM_b_ $RoomMTO_b_1
     */
    public function removeRoomMTO_b_1 (\DctrBundle\Entity\RoomMTO_b_1 $roomMTO_b_1)
    {

        if( $roomMTO_b_1->getAddrOTM_b_()->getId() == $this->id ) {
            $roomMTO_b_1->setAddrOTM_b_(null);
        } //

        if ( $this->hasRoomMTO_b_1($roomMTO_b_1) ) {  
            $this->roomMTO_b_1->removeElement($roomMTO_b_1);
         } // else if ( !$this->hasRoomMTO_b_1($roomMTO_b_1) ) 

    } //remove  


    /**
     * Add RoomMTO_b_1
     *
     * @param DctrBundle\Entity\AddrOTM_b_ $RoomMTO_b_1
     *
     * @return RoomMTO_b_1
     */
    public function addRoomMTO_b_1(\DctrBundle\Entity\RoomMTO_b_1 $roomMTO_b_1)
    { 
        if(!$roomMTO_b_1 instanceof \DctrBundle\Entity\RoomMTO_b_1) {
            throw new \InvalidArgumentException('$roomMTO_b_1 must be null or instance of DctrBundle\Entity\RoomMTO_b_1'); 
        }
        else if ( !$this->hasRoomMTO_b_1($roomMTO_b_1) ) { 

            $this->roomMTO_b_1->add($roomMTO_b_1); 
            //echo "<br> 150,addRoomMTO_b_1 setting room to address in ".__FILE__;

            if ( !$roomMTO_b_1->hasAddrOTM_b_($this) ) { 
                $roomMTO_b_1->setAddrOTM_b_($this);
            }       

        } // else if ( !$this->hasRoomMTO_b_1($RoomMTO_b_1) ) {

        return $this;        

    } //

    /**
     * @param DctrBundle\Entity\AddrOTM_b_ $RoomMTO_b_1
     * @return bool
     */
    public function hasRoomMTO_b_1($roomMTO_b_1)
    {
        return $this->getRoomMTO_b_1()->contains($roomMTO_b_1);
    }   



    /**
     * Return Entity as string  
     * 
     * @return string String representation of this class
     */
    public function __toString()
    {
        return strval($this->id);
    }            

 } //class AddrOTM_b_ {

1 个答案:

答案 0 :(得分:0)

原因是语法错误,错误 - remove,右 - removeElement

错误的房间实体setAddrOTM_b _($ addr):

if( $this->addrOTM_b_ -> getRoomMTO_b_1() -> contains($this) ) {
   $this->addrOTM_b_ -> getRoomMTO_b_1() -> remove($this);  
} 

房间实体中的右侧setAddrOTM_b _($ addr):

if( $this->addrOTM_b_ -> getRoomMTO_b_1() -> contains($this) ) {
    $this->addrOTM_b_ -> getRoomMTO_b_1() -> removeElement($this); 
}