Как убрать задолженную сторону со стороны обратной связи MTO без каскадной опции? Как обновить обратную сторону отношения?
Как убрать текущую сторону с обратной стороны MTO без каскадной опции? Как обновить обратную сторону отношения без каскадного варианта?
Ошибка в том, что если я изменяю адрес (OTM) комнаты (MTO), комната остается на прежнем адресе, хотя я удаляю его.
if( $this->addrOTM_b_ -> getRoomMTO_b_1() -> contains($this) ) {
$this->addrOTM_b_ -> getRoomMTO_b_1() -> remove($this);
}
Если я проверю адрес комнаты - это правильный новый адрес. Но если я проверю номера в адресе, они ошибаются, потому что существуют номера, которые были удалены.
Может быть, есть порядок, как я буду сбрасывать сущности? Или порядок, как я буду снимать номера с адресов? Или, возможно, это невозможно сделать на уровне сущности, и я сделаю это на уровне действия контроллера?
У этого поста есть комментарий, что это невозможно: Доктрина: невозможно удалить элемент из обратной стороны отношения
Это просто иллюстрация о двунаправленном отношении MTO. Обычно трудно перенести комнату на другой адрес, если это не лодка / палатка / фургон.
PS Я знаю, что это не очень хорошо для очистки внутри цикла 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 ответ
Причиной был неправильный синтаксис, НЕПРАВИЛЬНО - 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);
}