Как убрать задолженную сторону со стороны обратной связи 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); 
} 
Другие вопросы по тегам