How to remove owing side from inversed MTO relation side without cascade option? , how to update the inversed side of relation without cascade option?
Error is that if i change address(OTM) of the room (MTO), room remains in the previous address, although i remove it .
if( $this->addrOTM_b_ -> getRoomMTO_b_1() -> contains($this) ) {
$this->addrOTM_b_ -> getRoomMTO_b_1() -> remove($this);
}
If i check the address of the room - it is correct new address. But if i check the rooms in the address, they are wrong, because exists rooms which have been removed.
Maybe there is an order how i shall flush entities? Or an order how i shall remove rooms from addresses? Or maybe it is not possible to make at level of entity, and i shall make this at level of Controller action?
This post has a coment that it is not possible:Doctrine: can't removeElement from inverse side of the relation
This is just an illustration about bidirectional MTO relation, Normally it is difficult to transfer room to another address, unless it is a boat/tent/van.
p.s. I know that it is not good to flush inside the foreach loop, but i can not clear entity manager, because i will use entities in the second loop. Anyway these loops are litte, thre are only 5 addresses and 20 rooms.
//Controller action, kind of fixture
//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' ) {
//Room entity
<?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 {
//Address entity
<?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_ {