PersistentCollection::clear() and removeElement() with orphanRemoval #5579

Open
opened 2026-01-22 15:11:50 +01:00 by admin · 5 comments
Owner

Originally created by @steevanb on GitHub (Jun 19, 2017).

Hi !

I have a simple User entity, linked to Comment by oneToMany, with orphanRemoval:

class User
{
    protected $comments;

    public function __construct()
    {
        $this->comments = new ArrayCollection();
    }

    public function getComments(): Collection
    {
        return $this->comments;
    }

    public function addComment(Comment $comment): self
    {
        if ($this->comments->contains($comment) === false) {
            $this->comments->add($comment);
            $comment->setUser($this);
        }

        return $this;
    }
}
class Comment
{
    protected $user;

    public function setUser(?User $user): self
    {
        $this->user = $user;

        return $this;
    }

    public function getUser(): ?User
    {
        return $this->user;
    }
}

if i call that:

$user = $repositoryUser->find(1);
foreach ($user->getComments() as $comment) {
    $user->getComments()->removeElement($comment);
    $user->addComment($comment);
}

$manager->flush();

or that:

$comment = $user->getComments()->first();
$user->getComments()->clear();
$user->addComment($comment);

$manager->flush();

Finally, Comment entity will be deleted.

Why ? Cause in PersistentCollection::clear() and removeElement(), orphanRemoval will add your deleted entity in UnitOfWork::$orphanRemovals.
flush() will read UnitOfWork::$orphanRemovals, and delete all entities, although they are deleted then added
See https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/PersistentCollection.php#L395 and https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/PersistentCollection.php#L560

How can i delete then add same entity, with orphanRemoval ?

Originally created by @steevanb on GitHub (Jun 19, 2017). Hi ! I have a simple User entity, linked to Comment by oneToMany, with orphanRemoval: ```php class User { protected $comments; public function __construct() { $this->comments = new ArrayCollection(); } public function getComments(): Collection { return $this->comments; } public function addComment(Comment $comment): self { if ($this->comments->contains($comment) === false) { $this->comments->add($comment); $comment->setUser($this); } return $this; } } ``` ```php class Comment { protected $user; public function setUser(?User $user): self { $this->user = $user; return $this; } public function getUser(): ?User { return $this->user; } } ``` if i call that: ```php $user = $repositoryUser->find(1); foreach ($user->getComments() as $comment) { $user->getComments()->removeElement($comment); $user->addComment($comment); } $manager->flush(); ``` or that: ```php$user = $repositoryUser->find(1); $comment = $user->getComments()->first(); $user->getComments()->clear(); $user->addComment($comment); $manager->flush(); ``` Finally, Comment entity will be deleted. Why ? Cause in PersistentCollection::clear() and removeElement(), orphanRemoval will add your deleted entity in UnitOfWork::$orphanRemovals. flush() will read UnitOfWork::$orphanRemovals, and delete all entities, **although they are deleted then added** See https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/PersistentCollection.php#L395 and https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/PersistentCollection.php#L560 How can i delete then add same entity, with orphanRemoval ?
admin added the BugMissing Tests labels 2026-01-22 15:11:50 +01:00
Author
Owner

@alcaeus commented on GitHub (Jun 19, 2017):

Cross-referencing doctrine/mongodb-odm#1248, where we solved the same issue by unscheduling orphan removal in PersistentCollection::add

@alcaeus commented on GitHub (Jun 19, 2017): Cross-referencing doctrine/mongodb-odm#1248, where we solved the same issue by unscheduling orphan removal in PersistentCollection::add
Author
Owner

@steevanb commented on GitHub (Jun 19, 2017):

Looks good, but why this is not fixed for every databases ? Like MySQL ?

@steevanb commented on GitHub (Jun 19, 2017): Looks good, but why this is not fixed for every databases ? Like MySQL ?
Author
Owner

@alcaeus commented on GitHub (Jun 19, 2017):

@steevanb Because I only maintain ODM where I originally found the issue. I haven't used an SQL based database in years. I'll try to port the fix over to ORM.

@alcaeus commented on GitHub (Jun 19, 2017): @steevanb Because I only maintain ODM where I originally found the issue. I haven't used an SQL based database in years. I'll try to port the fix over to ORM.
Author
Owner

@steevanb commented on GitHub (Jun 19, 2017):

Ok thanks !

@steevanb commented on GitHub (Jun 19, 2017): Ok thanks !
Author
Owner

@lcobucci commented on GitHub (Jun 23, 2017):

@steevanb could you please send us a PR with a functional test that reproduces this behaviour? Sending just an example doesn't give us the complete overview of things and why it fails. You can find examples on 971c400025/tests/Doctrine/Tests/ORM/Functional

@lcobucci commented on GitHub (Jun 23, 2017): @steevanb could you please send us a PR with a functional test that reproduces this behaviour? Sending just an example doesn't give us the complete overview of things and why it fails. You can find examples on https://github.com/doctrine/doctrine2/tree/971c40002522cfebe58d80aff21eef9fe439fa60/tests/Doctrine/Tests/ORM/Functional
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5579