Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-1452

ObjectHydrator bug: hydration of entity with self (cyclic) relation through ref entity

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 2.1, 2.1.1, 2.1.2
    • Fix Version/s: 2.2
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None

      Description

      ObjectHydrator has bug in hydrate entities with relation to entity of this same class throught reference entity. Example Model:

      EntityA

      • id
      • title (string)
      • entitiesB (annotation: @ORM\OneToMany(targetEntity="EntityB", mappedBy="entityAFrom"))

      EntityB

      • id
      • entityAFrom (annotation: @ORM\ManyToOne(targetEntity="EntityA", inversedBy="entitiesB"))
      • entityATo (annotation: @ORM\ManyToOne(targetEntity="EntityA"))
      • type (string)

      Scenario:

      Execution of dql query 'SELECT a, b, ba FROM EntityA AS a LEFT JOIN a.entitiesB AS b LEFT JOIN b.entityATo AS ba' with max results set to "1" and data in database:

      EntityATable:
      id | title
      1 | a
      2 | b

      EntityBTable:
      id | entityAFromId | entityAToId | type
      1 | 1 | 2 | type

      Resume:

      I expected collection of EntityA object (size=1 becouse I set max results to 1) with hydrated entitiesB collection (size=1 becouse in db is only 1 record) and hydrated entityTo object. entitiesB property of entityTo object should be empty PersistCollection (ready to lazy load) but is null...

      I can provide TestCase for this issue.

      1. DDC1452Test.php
        2 kB
        Piotr Śliwa
      2. DDC1452Test.php
        2 kB
        Benjamin Eberlei

        Activity

        Hide
        Benjamin Eberlei added a comment -

        Attached a working testcase.

        Please put it into tests/Doctrine/Tests/ORM/Functional/Ticket and run:

        phpunit --group DDC-1452
        

        Please make that test fail from your perspective, i think it reproduces your test-case exactly.

        Show
        Benjamin Eberlei added a comment - Attached a working testcase. Please put it into tests/Doctrine/Tests/ORM/Functional/Ticket and run: phpunit --group DDC-1452 Please make that test fail from your perspective, i think it reproduces your test-case exactly.
        Hide
        Piotr Śliwa added a comment - - edited

        Ok, I have fixed testcase to situation that I was talking about.

        I have hardly debuged this issue, problem is in ObjectHydrator::_getEntity() method. This method delegates to UnitOfWork::createEntity() and passes $hints array. In $hints array, data about fetching associations is stored. In situation when one entity is joined throught two different associations (as in this testcase, first time DDC1452EntityA is used in from clause, second time in join clause) hydrator "minds" that objects from second association have have loaded association that is connecting entities of the same type. In testcase this is "entitiesB" association of "ba" aliased entity. That occurs, becouse $hints['fetched']['Namespace\DDC1452EntityA']['entitiesB'] has already been set on true while hydrating DDC1452EntityA objects from "FROM" clause. If in testcase had not been set limit for results, then this test would have to pass, becouse second object of DDC1452EntityA ($a2) would have to be load propertly as entity from "FROM" clause.

        Show
        Piotr Śliwa added a comment - - edited Ok, I have fixed testcase to situation that I was talking about. I have hardly debuged this issue, problem is in ObjectHydrator::_getEntity() method. This method delegates to UnitOfWork::createEntity() and passes $hints array. In $hints array, data about fetching associations is stored. In situation when one entity is joined throught two different associations (as in this testcase, first time DDC1452EntityA is used in from clause, second time in join clause) hydrator "minds" that objects from second association have have loaded association that is connecting entities of the same type. In testcase this is "entitiesB" association of "ba" aliased entity. That occurs, becouse $hints ['fetched'] ['Namespace\DDC1452EntityA'] ['entitiesB'] has already been set on true while hydrating DDC1452EntityA objects from "FROM" clause. If in testcase had not been set limit for results, then this test would have to pass, becouse second object of DDC1452EntityA ($a2) would have to be load propertly as entity from "FROM" clause.
        Hide
        Benjamin Eberlei added a comment -

        The explaination makes sense. I will dig into it.

        Show
        Benjamin Eberlei added a comment - The explaination makes sense. I will dig into it.
        Hide
        Benjamin Eberlei added a comment -

        This is fixed, but only in master. The code change necessary was pretty serious so i dont want to merge it into the stable branch without more people testing it.

        Show
        Benjamin Eberlei added a comment - This is fixed, but only in master. The code change necessary was pretty serious so i dont want to merge it into the stable branch without more people testing it.
        Hide
        Piotr Śliwa added a comment -

        Great job, thanks!

        Show
        Piotr Śliwa added a comment - Great job, thanks!

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Piotr Śliwa
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: