DDC-531: Collections broken in self-referenced Entities #660

Closed
opened 2026-01-22 12:45:53 +01:00 by admin · 15 comments
Owner

Originally created by @doctrinebot on GitHub (Apr 20, 2010).

Jira issue originally created by user nicokaiser:

When dealing with parent / children entities, the UnitOfWork does not always hydrate all data correctly.

This example generates Group1 and its child Group2. Then Clears the Entity Manager, loads Group2 (so it is in the EM), loads Group1 and then the children of Group1 (Group2 is the child of Group1).
However the children of Group1 cannot be loaded, because $group4->children is not there:

Warning: Invalid argument supplied for foreach() in /Users/nico/Projects/test/test.php on line 20

When calling Debug::dump($group4), I get this:

object(stdClass)#56 (2) {
  ["*_CLASS_*"]=>
  string(26) "Proxies\EntitiesGroupProxy"
  ["id"]=>
  string(1) "1"
}

test.php
http://pastebin.com/7Q3wwtn6

Group entity:
http://pastebin.com/hBj2Emrf

Originally created by @doctrinebot on GitHub (Apr 20, 2010). Jira issue originally created by user nicokaiser: When dealing with parent / children entities, the UnitOfWork does not always hydrate all data correctly. This example generates Group1 and its child Group2. Then Clears the Entity Manager, loads Group2 (so it is in the EM), loads Group1 and then the children of Group1 (Group2 is the child of Group1). However the children of Group1 cannot be loaded, because $group4->children is not there: `Warning: Invalid argument supplied for foreach() in /Users/nico/Projects/test/test.php on line 20` When calling Debug::dump($group4), I get this: ``` object(stdClass)#56 (2) { ["*_CLASS_*"]=> string(26) "Proxies\EntitiesGroupProxy" ["id"]=> string(1) "1" } ``` test.php http://pastebin.com/7Q3wwtn6 Group entity: http://pastebin.com/hBj2Emrf
admin added the Bug label 2026-01-22 12:45:53 +01:00
admin closed this issue 2026-01-22 12:45:53 +01:00
Author
Owner

@doctrinebot commented on GitHub (Apr 20, 2010):

Comment created by nicokaiser:

If I clear the Entity Manager between lines 17 and 18, it works... Seems like the previously loaded Group is reused (which is perfectly fine), but its associations (or at least its self-referenced associations) are not loaded (neither proxies are generated)...

@doctrinebot commented on GitHub (Apr 20, 2010): Comment created by nicokaiser: If I clear the Entity Manager between lines 17 and 18, it works... Seems like the previously loaded Group is reused (which is perfectly fine), but its associations (or at least its self-referenced associations) are not loaded (neither proxies are generated)...
Author
Owner

@doctrinebot commented on GitHub (Apr 23, 2010):

Comment created by romanb:

Thanks for reporting. I will take a look as soon as I find the time.

@doctrinebot commented on GitHub (Apr 23, 2010): Comment created by romanb: Thanks for reporting. I will take a look as soon as I find the time.
Author
Owner

@doctrinebot commented on GitHub (Apr 23, 2010):

Comment created by nicokaiser:

Test case for Doctrine\Tests\ORM\Functional\Ticket

@doctrinebot commented on GitHub (Apr 23, 2010): Comment created by nicokaiser: Test case for Doctrine\Tests\ORM\Functional\Ticket
Author
Owner

@doctrinebot commented on GitHub (May 7, 2010):

Comment created by shurakai:

It might be worth noting that, after renaming $parent to $parent2, the object is loaded but $item4->children remains empty.

If $item3 isn't being fetched beforehands, then everything seems to work fine.

@doctrinebot commented on GitHub (May 7, 2010): Comment created by shurakai: It might be worth noting that, after renaming $parent to $parent2, the object is loaded but $item4->children remains empty. If $item3 isn't being fetched beforehands, then everything seems to work fine.
Author
Owner

@doctrinebot commented on GitHub (May 12, 2010):

Comment created by shurakai:

After investigating, it came to my mind that the test submitted uses

$proxy->publicProperty

instead of

$proxy->getPublicProperty()

Therefore, the proxy is not initialized and thus we get unexpected behaviour. Adding a getter a la "getChildren()" and calling this method only, everything works fine.

Therefore, I mark this ticket as invalid.

@doctrinebot commented on GitHub (May 12, 2010): Comment created by shurakai: After investigating, it came to my mind that the test submitted uses $proxy->publicProperty instead of $proxy->getPublicProperty() Therefore, the proxy is not initialized and thus we get unexpected behaviour. Adding a getter a la "getChildren()" and calling this method only, everything works fine. Therefore, I mark this ticket as invalid.
Author
Owner

@doctrinebot commented on GitHub (May 12, 2010):

Comment created by nicokaiser:

Shouldn't these properties be automagically instantiated? In our project, we did use getChildren() and it did not work either (sorry, can't provide test case now, will do on monday).

I think collections are populated automatically everywhere (you can always use $this->children in entities), so this should work here as well.

@doctrinebot commented on GitHub (May 12, 2010): Comment created by nicokaiser: Shouldn't these properties be automagically instantiated? In our project, we did use getChildren() and it did not work either (sorry, can't provide test case now, will do on monday). I think collections are populated automatically everywhere (you can always use $this->children in entities), so this should work here as well.
Author
Owner

@doctrinebot commented on GitHub (May 12, 2010):

Comment created by shurakai:

The problem here is, that you're not really using an entity but a proxy object. A proxy object does not initialize its collections, see here: http://www.doctrine-project.org/documentation/manual/2_0/en/best-practices#don%27t-use-public-properties-on-entities

As long as you're using normal entities, the PersistentCollections will normally lazy load, thats true. But as soon as you're using proxies - like in this case - you're running into severe problems. I strongly recommend not using public properties.

@doctrinebot commented on GitHub (May 12, 2010): Comment created by shurakai: The problem here is, that you're not really using an **entity** but a proxy object. A proxy object does not initialize its collections, see here: http://www.doctrine-project.org/documentation/manual/2_0/en/best-practices#don%27t-use-public-properties-on-entities As long as you're using normal entities, the PersistentCollections will normally lazy load, thats true. But as soon as you're using proxies - like in this case - you're running into severe problems. I strongly recommend not using public properties.
Author
Owner

@doctrinebot commented on GitHub (May 17, 2010):

Comment created by nicokaiser:

You are right - if I use getChildren and a "protected $children", this example works.
However, if I use inheritance (e.g. SINGLE_TABLE), it breaks again, even if I don't use sub items. I'll update the test case.

@doctrinebot commented on GitHub (May 17, 2010): Comment created by nicokaiser: You are right - if I use getChildren and a "protected $children", this example works. However, if I use inheritance (e.g. SINGLE_TABLE), it breaks again, even if I don't use sub items. I'll update the test case.
Author
Owner

@doctrinebot commented on GitHub (May 17, 2010):

Comment created by nicokaiser:

Updated DDC531Test.php to use SINGLE_TABLE inheritance. Breaks again, even if I don't use public members for the collection...

@doctrinebot commented on GitHub (May 17, 2010): Comment created by nicokaiser: Updated DDC531Test.php to use SINGLE_TABLE inheritance. Breaks again, even if I don't use public members for the collection...
Author
Owner

@doctrinebot commented on GitHub (May 17, 2010):

Comment created by shurakai:

Hi Nico,

thanks for your response. I will take a look at this issue shortly and will hopefully resolve it before beta2.

regards
christian

@doctrinebot commented on GitHub (May 17, 2010): Comment created by shurakai: Hi Nico, thanks for your response. I will take a look at this issue shortly and will hopefully resolve it before beta2. regards christian
Author
Owner

@doctrinebot commented on GitHub (May 20, 2010):

Comment created by romanb:

Thanks for your investigation. I tracked down the issue and have a fix pending.

Note though, that with such an example as in the provided testcase, the parents can never be lazy. That means all parents will be eagerly loaded. Of course you can work around that by eager-joining them in DQL or by using Query::HINT_FORCE_PARTIAL_LOAD and things like that.

The reason why the parents in the example can not be lazy is because a parent can potentially be of any subtype, so you would not know which proxy to put in. In general, a single-valued association that points to another entity that has mapped subclasses can not be lazy. This "problem" does not occur when the targeted entity has no mapped subclasses (this means it either does not participate in a mapped inheritance hierarchy or it is a leaf in the hierarchy).

See also: http://www.doctrine-project.org/jira/browse/DDC-357

@doctrinebot commented on GitHub (May 20, 2010): Comment created by romanb: Thanks for your investigation. I tracked down the issue and have a fix pending. Note though, that with such an example as in the provided testcase, the parents can never be lazy. That means all parents will be eagerly loaded. Of course you can work around that by eager-joining them in DQL or by using Query::HINT_FORCE_PARTIAL_LOAD and things like that. The reason why the parents in the example can not be lazy is because a parent can potentially be of any subtype, so you would not know which proxy to put in. In general, a single-valued association that points to another entity that has mapped subclasses can not be lazy. This "problem" does not occur when the targeted entity has no mapped subclasses (this means it either does not participate in a mapped inheritance hierarchy or it is a leaf in the hierarchy). See also: http://www.doctrine-project.org/jira/browse/[DDC-357](http://www.doctrine-project.org/jira/browse/DDC-357)
Author
Owner

@doctrinebot commented on GitHub (May 23, 2010):

Comment created by romanb:

Fixed in 616f2eda0a

@doctrinebot commented on GitHub (May 23, 2010): Comment created by romanb: Fixed in http://github.com/doctrine/doctrine2/commit/616f2eda0af1a15ba205cc5013b5f001c34dfc55
Author
Owner

@doctrinebot commented on GitHub (May 23, 2010):

Issue was closed with resolution "Fixed"

@doctrinebot commented on GitHub (May 23, 2010): Issue was closed with resolution "Fixed"
Author
Owner

@doctrinebot commented on GitHub (Mar 23, 2014):

Comment created by @doctrinebot:

A related Github Pull-Request [GH-970] was closed:
https://github.com/doctrine/doctrine2/pull/970

@doctrinebot commented on GitHub (Mar 23, 2014): Comment created by @doctrinebot: A related Github Pull-Request [GH-970] was closed: https://github.com/doctrine/doctrine2/pull/970
Author
Owner

@doctrinebot commented on GitHub (Dec 13, 2015):

Imported 1 attachments from Jira into https://gist.github.com/45247193c4df2d1e03a2

@doctrinebot commented on GitHub (Dec 13, 2015): Imported 1 attachments from Jira into https://gist.github.com/45247193c4df2d1e03a2 - [10606_DDC531Test.php](https://gist.github.com/45247193c4df2d1e03a2#file-10606_DDC531Test-php)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#660