Replies: 1 comment
|
Your hunch at the bottom is right, this is Doctrine rather than Symfony, and it's working as designed even though the result is genuinely surprising.
Which is why flushing first makes it behave. After the flush the database agrees with memory, so the load can't contradict you. The fix I'd reach for isn't ordering your calls carefully, because that's a rule you have to remember forever. It's keeping both sides of the association in sync in the entity itself, so the in-memory object graph is already correct and the lazy load has nothing to disagree with: public function setManySide(?ManySide $manySide): static
{
if (null !== $this->ManySide && $this->ManySide !== $manySide) {
$this->ManySide->removeOneSide($this);
}
$this->ManySide = $manySide;
if (null !== $manySide && !$manySide->getOneSides()->contains($this)) {
$manySide->addOneSide($this);
}
return $this;
}This is the part MakerBundle leaves to you on the owning side, and this scenario is more or less the reason it matters. Worth noting the naming is going to confuse whoever reads this next, since If you do want to raise it somewhere, doctrine/orm is the repo, though I'd expect the answer there to be the same. |
Uh oh!
There was an error while loading. Please reload this page.
Symfony version(s) affected
7.4.17 (at least from 7.4.14)
Description
Relation M2O/O2M.
Persistence lost when accessing the otherside before flushing.
Set initial value
$m1 = $this->manySideRepository->findOneByTitle("un");$m3 = $this->manySideRepository->findOneByTitle("trois");$o1 = $this->oneSideRepository->findOneByTitle('o1');$o1->setManySide($m1);$this->em->persist($o1);$this->em->flush();access before flush
$o1->setManySide($m3);$this->em->persist($o1);$io->note($o1->getManySide()->getTitle());foreach ($m1->getOneSides() as $o) {$io->info($o->getTitle());}$this->em->flush();$io->note($o1->getManySide()->getTitle());=>
! [NOTE] trois
[INFO] o1
! [NOTE] un
** flush before access **
$o1->setManySide($m3);$this->em->persist($o1);$this->em->flush();$io->note($o1->getManySide()->getTitle());foreach ($m1->getOneSides() as $o) {$io->info($o->getTitle());}$io->note($o1->getManySide()->getTitle());=>
! [NOTE] trois
! [NOTE] trois
How to reproduce
Make a M2O relation
Owning side : change the value , persist, access to the old value, then flush
Possible Solution
No response
Additional Context
doctrine problem may be
All reactions