OrphanRemoval does not work with ArrayCollection and manual persist which is not mentioned in the docs #6993

Open
opened 2026-01-22 15:42:45 +01:00 by admin · 0 comments
Owner

Originally created by @olsavmic on GitHub (Jun 15, 2022).

Bug Report

Q A
BC Break no
Version 2.11.x

Summary

I'd say this issue does not have a simple solution and it just requires documentation change.

Assume we have following entities:

#[Entity]
class Foo
{

    #[OneToMany(mappedBy: "foo", targetEntity: Bar::class, orphanRemoval: true)]
    public Collection $collection;

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

}

#[Entity]
class Bar
{

    #[JoinColumn]
    #[ManyToOne(targetEntity: Foo::class, inversedBy: "collection")]
    public Foo $foo;

}

Current behavior

Following code will create an entity even though the collection should be empty:

$foo = new Foo();
$bar = new Bar();

$bar->foo = $foo;
$entityManager->persist($bar);
$foo->collection->add($bar);

$foo->collection->clear();

// Bar will be created in the DB and hydrated on refresh
$entityManager->flush();

The issue is caused by combination of orphanRemoval with manually calling $entityManager->persist($entity) which is hard to fix (as ArrayCollection does not have access to entity manager) yet undocumented so unexpected.

Following code will work as expected:

// Working - Bar will be created & deleted
$foo = new Foo();
$bar = new Bar();

$bar->foo = $foo;
$entityManager->persist($bar);
$foo->collection->add($bar);

// Now the collection becomes PersistentCollection which does propagate changes to UnitOfWork
$entityManager->flush();

$foo->collection->clear();

$entityManager->flush();

Expected behavior

The only possible solution that comes to my mind is to document this behavior in orphanRemoval part and recommend using it alongside cascade=["persist"]

Originally created by @olsavmic on GitHub (Jun 15, 2022). ### Bug Report <!-- Fill in the relevant information below to help triage your issue. --> | Q | A |------------ | ------ | BC Break | no | Version | 2.11.x #### Summary I'd say this issue does not have a simple solution and it just requires documentation change. Assume we have following entities: ```php #[Entity] class Foo { #[OneToMany(mappedBy: "foo", targetEntity: Bar::class, orphanRemoval: true)] public Collection $collection; public function __construct() { $this->collection = new ArrayCollection(); } } #[Entity] class Bar { #[JoinColumn] #[ManyToOne(targetEntity: Foo::class, inversedBy: "collection")] public Foo $foo; } ``` #### Current behavior Following code will create an entity even though the collection should be empty: ```php $foo = new Foo(); $bar = new Bar(); $bar->foo = $foo; $entityManager->persist($bar); $foo->collection->add($bar); $foo->collection->clear(); // Bar will be created in the DB and hydrated on refresh $entityManager->flush(); ``` The issue is caused by combination of `orphanRemoval` with manually calling `$entityManager->persist($entity)` which is hard to fix (as ArrayCollection does not have access to entity manager) yet undocumented so unexpected. Following code will work as expected: ```php // Working - Bar will be created & deleted $foo = new Foo(); $bar = new Bar(); $bar->foo = $foo; $entityManager->persist($bar); $foo->collection->add($bar); // Now the collection becomes PersistentCollection which does propagate changes to UnitOfWork $entityManager->flush(); $foo->collection->clear(); $entityManager->flush(); ``` #### Expected behavior The only possible solution that comes to my mind is to document this behavior in `orphanRemoval` part and recommend using it alongside `cascade=["persist"]`
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#6993