Synchronization of bidirectional association cannot be performed in any order #5624

Open
opened 2026-01-22 15:13:07 +01:00 by admin · 4 comments
Owner

Originally created by @janedbal on GitHub (Jul 31, 2017).

Let's have following entities:

/** @ORM\Entity */
class RoomType {
	/** @ORM\OneToMany(targetEntity=Room::class, mappedBy="roomType") */
	private $rooms;

	public function addRoom(Room $room) {
		$this->rooms->add($room);
	}

	public function removeRoom(Room $room)	{
		$this->rooms->removeElement($room);
	}
}
/** @ORM\Entity */
class Room {
	/** @ORM\ManyToOne(targetEntity=RoomType::class, inversedBy="rooms") */
	private $roomType;

	public function moveTo(RoomType $roomType) {
		$oldRoomType = $this->roomType;
		$this->roomType = $roomType;
		$roomType->addRoom($this);
		$oldRoomType->removeRoom($this); // changes $this->roomType back to $oldRoomType !
	}
}

(full example, failing test: #6591)

Calling method moveTo will never update association from Room to new RoomType, because removeElement on PersistentCollection magically changes reference on Room::$roomType back to the old value. To make this work, you first have to remove old association and then create new like this:

$this->roomType->removeRoom($this);
$this->roomType = $roomType;
$roomType->addRoom($this);

Is there any reason, why Doctrine behaves like this? From my point of view, this looks like a bug.

Originally created by @janedbal on GitHub (Jul 31, 2017). Let's have following entities: ```php /** @ORM\Entity */ class RoomType { /** @ORM\OneToMany(targetEntity=Room::class, mappedBy="roomType") */ private $rooms; public function addRoom(Room $room) { $this->rooms->add($room); } public function removeRoom(Room $room) { $this->rooms->removeElement($room); } } /** @ORM\Entity */ class Room { /** @ORM\ManyToOne(targetEntity=RoomType::class, inversedBy="rooms") */ private $roomType; public function moveTo(RoomType $roomType) { $oldRoomType = $this->roomType; $this->roomType = $roomType; $roomType->addRoom($this); $oldRoomType->removeRoom($this); // changes $this->roomType back to $oldRoomType ! } } ``` ([full example](https://gist.github.com/janedbal/f910792334a51a561623d3d6fc5b5430), failing test: #6591) Calling method **moveTo** will never update association from Room to new RoomType, because removeElement on PersistentCollection magically changes reference on `Room::$roomType` back to the old value. To make this work, you first have to remove old association and then create new like this: ```php $this->roomType->removeRoom($this); $this->roomType = $roomType; $roomType->addRoom($this); ``` Is there any reason, why Doctrine behaves like this? From my point of view, this looks like a bug.
admin added the BugMissing Tests labels 2026-01-22 15:13:07 +01:00
Author
Owner

@Ocramius commented on GitHub (Jul 31, 2017):

PersistentCollection magically changes reference on Room::$roomType back to the old value

A test is needed to verify this. The code as-is seems sane, and a unit test around the Room class probably shows that the values are correct when not involving Doctrine ORM, but with Doctrine ORM plus your code involved, we need some sort of proof that there is a problem.

See https://github.com/doctrine/doctrine2/tree/master/tests/Doctrine/Tests/ORM/Functional/Ticket for examples on such tests.

@Ocramius commented on GitHub (Jul 31, 2017): > PersistentCollection magically changes reference on Room::$roomType back to the old value A test is needed to verify this. The code as-is seems sane, and a unit test around the `Room` class probably shows that the values are correct when not involving Doctrine ORM, but with Doctrine ORM plus your code involved, we need some sort of proof that there is a problem. See https://github.com/doctrine/doctrine2/tree/master/tests/Doctrine/Tests/ORM/Functional/Ticket for examples on such tests.
Author
Owner

@janedbal commented on GitHub (Jul 31, 2017):

Ok, I'll send failing test to prove described behaviour.

@janedbal commented on GitHub (Jul 31, 2017): Ok, I'll send failing test to prove described behaviour.
Author
Owner

@janedbal commented on GitHub (Aug 1, 2017):

@Ocramius Failing test added: #6591

@janedbal commented on GitHub (Aug 1, 2017): @Ocramius Failing test added: #6591
Author
Owner

@FireLizard commented on GitHub (Oct 29, 2021):

I've got the same issue although fetch="EXTRA_LAZY" is set on the OneToMany association.
Are there any news on this?

@FireLizard commented on GitHub (Oct 29, 2021): I've got the same issue although `fetch="EXTRA_LAZY"` is set on the OneToMany association. Are there any news on this?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5624