DDC-2701: Collections in originalEntityData gets over written #3382

Closed
opened 2026-01-22 14:18:57 +01:00 by admin · 10 comments
Owner

Originally created by @doctrinebot on GitHub (Sep 23, 2013).

Originally assigned to: @Ocramius on GitHub.

Jira issue originally created by user tklein:

I was trying to use the UnitOfWork::getOriginalEntityData method and i noticed that if there is a collection in that object, it changes in the uow original datas when i change it on my original object

In my case the collection is ManyToMany unidirectional

I think this happens because both the uow and the object work with the same reference to the collection
maybe adding a clone of the collection instead of the real one, i don't know if it is possible

Thank you for taking a look and for Doctrine!

Tom

Originally created by @doctrinebot on GitHub (Sep 23, 2013). Originally assigned to: @Ocramius on GitHub. Jira issue originally created by user tklein: I was trying to use the UnitOfWork::getOriginalEntityData method and i noticed that if there is a collection in that object, it changes in the uow original datas when i change it on my original object In my case the collection is ManyToMany unidirectional I think this happens because both the uow and the object work with the same reference to the collection maybe adding a clone of the collection instead of the real one, i don't know if it is possible Thank you for taking a look and for Doctrine! Tom
admin added the Bug label 2026-01-22 14:18:57 +01:00
admin closed this issue 2026-01-22 14:18:57 +01:00
Author
Owner

@doctrinebot commented on GitHub (Aug 18, 2014):

Comment created by @ocramius:

This issue needs a test case in order to be reproduced.

@doctrinebot commented on GitHub (Aug 18, 2014): Comment created by @ocramius: This issue needs a test case in order to be reproduced.
Author
Owner

@doctrinebot commented on GitHub (Aug 20, 2014):

Comment created by tklein:

Here is how i get to this bug:

2 entities with a many to many unidirectional relation:

class Conversation
{
    // ...........

    /****
     * @ORM\ManyToMany(targetEntity="User")
     * @ORM\JoinTable(name="Conversations*To*Users",
     *      joinColumns={@ORM\JoinColumn(name="conversation_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
     * )
     *
     * @var ArrayCollection
     */
    private $users;

    public function getUsers()
    {
        return $this->users();
    }

    // .....
}

class User
{
    // .....
}

Load the Conversation entity joined with the associated users: you get a Conversation entity with the users property filled with a PersistentCollection initialized. You can find this object in the originalEntityData property of the unit of work.

Then do:

$users = $conversation->getUsers();
$users->remove(0);

In the conversation object, the first user of the collection has been removed. In the unit of work, find the corresponding object in the originalEntityData array and you'll see that the first user has been removed from the collection too. It is then not possible to use the originalEntityData on joined collection to check for changes

@doctrinebot commented on GitHub (Aug 20, 2014): Comment created by tklein: Here is how i get to this bug: 2 entities with a many to many unidirectional relation: ``` class Conversation { // ........... /**** * @ORM\ManyToMany(targetEntity="User") * @ORM\JoinTable(name="Conversations*To*Users", * joinColumns={@ORM\JoinColumn(name="conversation_id", referencedColumnName="id")}, * inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")} * ) * * @var ArrayCollection */ private $users; public function getUsers() { return $this->users(); } // ..... } class User { // ..... } ``` Load the Conversation entity joined with the associated users: you get a Conversation entity with the users property filled with a PersistentCollection initialized. You can find this object in the originalEntityData property of the unit of work. Then do: ``` $users = $conversation->getUsers(); $users->remove(0); ``` In the conversation object, the first user of the collection has been removed. In the unit of work, find the corresponding object in the originalEntityData array and you'll see that the first user has been removed from the collection too. It is then not possible to use the originalEntityData on joined collection to check for changes
Author
Owner

@doctrinebot commented on GitHub (Aug 20, 2014):

Comment created by @ocramius:

[~tklein] still not sure what the problem is:

$user         = new User();
$conversation = new Conversation();

$conversation->addUser($user);

$em->persist($user);
$em->persist($conversation);
$em->flush();
$em->clear();

$conversation1   = $em->find('Conversation', $conversation->id);
$usersCollection = $conversation->getUsers();

$usersCollection->remove(0);

var_dump($em->getUnitOfWork()->getOriginalEntityData($conversation1));

// what is failing after this point?

This is also how a test case should look like when thrown at the ORM functional test suite: https://github.com/doctrine/doctrine2/tree/v2.4.4/tests/Doctrine/Tests/ORM/Functional/Ticket

@doctrinebot commented on GitHub (Aug 20, 2014): Comment created by @ocramius: [~tklein] still not sure what the problem is: ``` $user = new User(); $conversation = new Conversation(); $conversation->addUser($user); $em->persist($user); $em->persist($conversation); $em->flush(); $em->clear(); $conversation1 = $em->find('Conversation', $conversation->id); $usersCollection = $conversation->getUsers(); $usersCollection->remove(0); var_dump($em->getUnitOfWork()->getOriginalEntityData($conversation1)); // what is failing after this point? ``` This is also how a test case should look like when thrown at the ORM functional test suite: https://github.com/doctrine/doctrine2/tree/v2.4.4/tests/Doctrine/Tests/ORM/Functional/Ticket
Author
Owner

@doctrinebot commented on GitHub (Aug 20, 2014):

Comment created by tklein:

Sorry i'll try to write a real test case asap ...

What is failing after this point ?

$origConversationData = $em->getUnitOfWork()->getOriginalEntityData($conversation1);
var_dump(count($origConversationData['users'])); // should be equal to 1, i get 0 ...

The only diff i can see with your example is that i'm not using find but a query with the relation fetched-joined in it so the collection is initialized

@doctrinebot commented on GitHub (Aug 20, 2014): Comment created by tklein: Sorry i'll try to write a real test case asap ... What is failing after this point ? ``` $origConversationData = $em->getUnitOfWork()->getOriginalEntityData($conversation1); var_dump(count($origConversationData['users'])); // should be equal to 1, i get 0 ... ``` The only diff i can see with your example is that i'm not using find but a query with the relation fetched-joined in it so the collection is initialized
Author
Owner

@doctrinebot commented on GitHub (Aug 20, 2014):

Comment created by @ocramius:

Collections are not tracked within entity data, but separately in the UoW

@doctrinebot commented on GitHub (Aug 20, 2014): Comment created by @ocramius: Collections are not tracked within entity data, but separately in the UoW
Author
Owner

@doctrinebot commented on GitHub (Aug 20, 2014):

Comment created by tklein:

Ok so i guess we can close this ticket if this is an expected behavior ...

In your last comment, did you mean:
Collections are not tracked within entity data, but each element of the collection is tracked separately in the UoW ?

Anyway thanks for your help

@doctrinebot commented on GitHub (Aug 20, 2014): Comment created by tklein: Ok so i guess we can close this ticket if this is an expected behavior ... In your last comment, did you mean: Collections are not tracked within entity data, but **each element of the collection is tracked** separately in the UoW ? Anyway thanks for your help
Author
Owner

@doctrinebot commented on GitHub (Oct 19, 2014):

Comment created by @ocramius:

I mean that collections are tracked by specific properties/states in the UoW: 9bf8f6ed4c/lib/Doctrine/ORM/UnitOfWork.php (L180-L192)

Yes, collection items are still single entities tracked in the UoW

@doctrinebot commented on GitHub (Oct 19, 2014): Comment created by @ocramius: I mean that collections are tracked by specific properties/states in the UoW: https://github.com/doctrine/doctrine2/blob/9bf8f6ed4cc6590def5b5e8ba739ecdfa62fb717/lib/Doctrine/ORM/UnitOfWork.php#L180-L192 Yes, collection items are still single entities tracked in the UoW
Author
Owner

@doctrinebot commented on GitHub (Oct 19, 2014):

Issue was closed with resolution "Invalid"

@doctrinebot commented on GitHub (Oct 19, 2014): Issue was closed with resolution "Invalid"
Author
Owner

@pascalwacker commented on GitHub (Mar 14, 2022):

I know this is a 7 year old issue, that's actually working as expected, however since I wasn't able to find anything in the docs, I'll just ask here: How would one get the changes in collections? In my case the keys of the changed entities would be enough

@pascalwacker commented on GitHub (Mar 14, 2022): I know this is a 7 year old issue, that's actually working as expected, however since I wasn't able to find anything in the docs, I'll just ask here: How would one get the changes in collections? In my case the keys of the changed entities would be enough
Author
Owner

@asdfMaciej commented on GitHub (Sep 14, 2023):

@pascalwacker It doesn't directly answer your question, but you can use internal getDeleteDiff() and getInsertDiff() methods in Collections

@asdfMaciej commented on GitHub (Sep 14, 2023): @pascalwacker It doesn't directly answer your question, but you can use internal `getDeleteDiff()` and `getInsertDiff()` methods in Collections
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#3382