Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-54

Trigger postLoad events and callbacks after associations have been initialized

    Details

      Description

      Currently the postLoad events and callbacks are triggered after the entity has been created and filled with its "primitive" state but before associations are available. The postLoad events and callbacks should be postponed so that they are triggered after associations have been initialized.

        Issue Links

          Activity

          Roman S. Borschel created issue -
          Hide
          Roman S. Borschel added a comment -

          If this is to be included in 2.0 it needs to happen for RC1. However, it is not clear yet whether it will be done in time.

          Show
          Roman S. Borschel added a comment - If this is to be included in 2.0 it needs to happen for RC1. However, it is not clear yet whether it will be done in time.
          Roman S. Borschel made changes -
          Field Original Value New Value
          Fix Version/s 2.0-RC1 [ 10091 ]
          Fix Version/s 2.0 [ 10021 ]
          Hide
          Benjamin Eberlei added a comment -

          How would you solve this Roman? I thought of adding a query hint so that the postLoad inside unit of work is not triggered and gathering all the entities that have a post load event in an array inside the object hydrator, then iterating it after taking the snapshots of all collections inside hydrateAll

          Show
          Benjamin Eberlei added a comment - How would you solve this Roman? I thought of adding a query hint so that the postLoad inside unit of work is not triggered and gathering all the entities that have a post load event in an array inside the object hydrator, then iterating it after taking the snapshots of all collections inside hydrateAll
          Hide
          Roman S. Borschel added a comment -

          @Benjamin: Not sure what you would use the query hint for but in general that is the approach I had in mind, yes. You can't get around iterating over the entities after the actual hydration.

          Show
          Roman S. Borschel added a comment - @Benjamin: Not sure what you would use the query hint for but in general that is the approach I had in mind, yes. You can't get around iterating over the entities after the actual hydration.
          Hide
          Benjamin Eberlei added a comment -

          The query hint would do something like:

                  //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here.
                  if (isset($class->lifecycleCallbacks[Events::postLoad]) && !isset($hints['hydrationPostLoad'])) {
                      $class->invokeLifecycleCallbacks(Events::postLoad, $entity);
                  }
                  if ($this->evm->hasListeners(Events::postLoad) && !isset($hints['hydrationPostLoad'])) {
                      $this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->em));
                  }
          

          another way would be to move that code out of UoW::createEntity completly and have the persisters call it when they use that method.

          Show
          Benjamin Eberlei added a comment - The query hint would do something like: //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here. if (isset($class->lifecycleCallbacks[Events::postLoad]) && !isset($hints['hydrationPostLoad'])) { $class->invokeLifecycleCallbacks(Events::postLoad, $entity); } if ($ this ->evm->hasListeners(Events::postLoad) && !isset($hints['hydrationPostLoad'])) { $ this ->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $ this ->em)); } another way would be to move that code out of UoW::createEntity completly and have the persisters call it when they use that method.
          Hide
          Roman S. Borschel added a comment -

          Leaving that code in UoW does not make sense to me, if it is moved, it needs to be moved completely. Why do you think the persisters should do it? Initially I thought collecting the affected entities during hydration and then when hydration is done iterating over them and triggering the postLoad events.

          Show
          Roman S. Borschel added a comment - Leaving that code in UoW does not make sense to me, if it is moved, it needs to be moved completely. Why do you think the persisters should do it? Initially I thought collecting the affected entities during hydration and then when hydration is done iterating over them and triggering the postLoad events.
          Hide
          Benjamin Eberlei added a comment -

          Yes but postLoad has to be triggered for non Hydrated entities (i.e. Persister) also

          Show
          Benjamin Eberlei added a comment - Yes but postLoad has to be triggered for non Hydrated entities (i.e. Persister) also
          Hide
          Benjamin Eberlei added a comment -

          Moved back

          Show
          Benjamin Eberlei added a comment - Moved back
          Benjamin Eberlei made changes -
          Assignee Roman S. Borschel [ romanb ] Benjamin Eberlei [ beberlei ]
          Fix Version/s 2.x [ 10090 ]
          Fix Version/s 2.0-RC1 [ 10091 ]
          Benjamin Eberlei made changes -
          Fix Version/s 2.1 [ 10022 ]
          Fix Version/s 2.x [ 10090 ]
          Benjamin Eberlei made changes -
          Fix Version/s 2.x [ 10090 ]
          Fix Version/s 2.1 [ 10022 ]
          Hide
          Kacper Gunia added a comment -

          Hi Gyus, I need access to associations in postLoad or similar event, and my idea is to dispatch new event after full initialisation of object, what do You think about it? If I can help please let me know It's important for me.

          Show
          Kacper Gunia added a comment - Hi Gyus, I need access to associations in postLoad or similar event, and my idea is to dispatch new event after full initialisation of object, what do You think about it? If I can help please let me know It's important for me.
          Benjamin Eberlei made changes -
          Workflow jira [ 10198 ] jira-feedback [ 13834 ]
          Benjamin Eberlei made changes -
          Workflow jira-feedback [ 13834 ] jira-feedback2 [ 15698 ]
          Benjamin Eberlei made changes -
          Workflow jira-feedback2 [ 15698 ] jira-feedback3 [ 17955 ]
          Collette Christophe made changes -
          Status Open [ 1 ] Awaiting Feedback [ 10000 ]
          made changes -
          Status Awaiting Feedback [ 10000 ] In Progress [ 3 ]
          Hide
          Alexander Pasichnick added a comment -

          Now in my PostLoad access to associations is work fine. Why this issue is still in Unresolved status?

          Show
          Alexander Pasichnick added a comment - Now in my PostLoad access to associations is work fine. Why this issue is still in Unresolved status?
          Hide
          Łukasz Cybula added a comment -

          What do you (Roman and Benjamin) think about adding postHydrate event which would be called within ObjectHydrator::hydrateAllData() on every entity collected during hydration? I could prepare a patch for this. I personally think this would be better than adding a hint that changes behaviour of postLoad event.

          Show
          Łukasz Cybula added a comment - What do you (Roman and Benjamin) think about adding postHydrate event which would be called within ObjectHydrator::hydrateAllData() on every entity collected during hydration? I could prepare a patch for this. I personally think this would be better than adding a hint that changes behaviour of postLoad event.
          Hide
          Slavik Derevyanko added a comment - - edited

          Just stumbled upon this issue. Seems like my associated entities aren't yet loaded in PostLoad event handler.
          Doctrine version "doctrine/orm": "2.3.1"

          I've noticed that I have two different paths of execution:
          1. When the find() method is used to retrieve the entity, SimpleObjectHydrator is used to perform a hydration and the associations are made available in PostLoad event:
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php.Doctrine\ORM\Mapping\ClassMetadataInfo->invokeLifecycleCallbacks : lineno 2312() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php at line 2312
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php.Doctrine\ORM\UnitOfWork->createEntity : lineno 2610() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 2610
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php.Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator->hydrateRowData : lineno 135() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php at line 135
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php.Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator->hydrateAllData : lineno 50() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php at line 50
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php.Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll : lineno 111() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php at line 111
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php.Doctrine\ORM\Persisters\BasicEntityPersister->load : lineno 678() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php at line 678
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php.Doctrine\ORM\EntityManager->find : lineno 413() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 413
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php.Doctrine\ORM\EntityRepository->find : lineno 131() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php at line 131

          2. When the DQL is used, ObjectHydrator is used to perform a hydration, and the associations aren't made ready in PostLoad event:
          bvdpetroleum/src/BVD/PetroleumBundle/Entity/FuelCard.php.BVD\PetroleumBundle\Entity\FuelCard->retrieveNumbers : lineno 304() bvdpetroleum/src/BVD/PetroleumBundle/Entity/FuelCard.php at line 304
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php.Doctrine\ORM\Mapping\ClassMetadataInfo->invokeLifecycleCallbacks : lineno 2312() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php at line 2312
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php.Doctrine\ORM\UnitOfWork->createEntity : lineno 2610() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 2610
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->_getEntity : lineno 245() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 245
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateRowData : lineno 478() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 478
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateAllData : lineno 149() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 149
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php.Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll : lineno 111() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php at line 111
          bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php.Doctrine\ORM\AbstractQuery->execute : lineno 747() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php at line 747

          Hope this helps to solve the issue.

          Show
          Slavik Derevyanko added a comment - - edited Just stumbled upon this issue. Seems like my associated entities aren't yet loaded in PostLoad event handler. Doctrine version "doctrine/orm": "2.3.1" I've noticed that I have two different paths of execution: 1. When the find() method is used to retrieve the entity, SimpleObjectHydrator is used to perform a hydration and the associations are made available in PostLoad event: bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php.Doctrine\ORM\Mapping\ClassMetadataInfo->invokeLifecycleCallbacks : lineno 2312() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php at line 2312 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php.Doctrine\ORM\UnitOfWork->createEntity : lineno 2610() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 2610 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php.Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator->hydrateRowData : lineno 135() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php at line 135 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php.Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator->hydrateAllData : lineno 50() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php at line 50 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php.Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll : lineno 111() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php at line 111 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php.Doctrine\ORM\Persisters\BasicEntityPersister->load : lineno 678() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php at line 678 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php.Doctrine\ORM\EntityManager->find : lineno 413() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 413 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php.Doctrine\ORM\EntityRepository->find : lineno 131() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php at line 131 2. When the DQL is used, ObjectHydrator is used to perform a hydration, and the associations aren't made ready in PostLoad event: bvdpetroleum/src/BVD/PetroleumBundle/Entity/FuelCard.php.BVD\PetroleumBundle\Entity\FuelCard->retrieveNumbers : lineno 304() bvdpetroleum/src/BVD/PetroleumBundle/Entity/FuelCard.php at line 304 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php.Doctrine\ORM\Mapping\ClassMetadataInfo->invokeLifecycleCallbacks : lineno 2312() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php at line 2312 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php.Doctrine\ORM\UnitOfWork->createEntity : lineno 2610() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 2610 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->_getEntity : lineno 245() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 245 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateRowData : lineno 478() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 478 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateAllData : lineno 149() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 149 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php.Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll : lineno 111() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php at line 111 bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php.Doctrine\ORM\AbstractQuery->execute : lineno 747() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php at line 747 Hope this helps to solve the issue.
          Hide
          Valera Leontyev added a comment -

          This issue is very important in my opinion. I can't come up with any workaround to resolve it. Only possible way to detect fully loaded state is to call entity method from outside which is too rude and dirty.

          Show
          Valera Leontyev added a comment - This issue is very important in my opinion. I can't come up with any workaround to resolve it. Only possible way to detect fully loaded state is to call entity method from outside which is too rude and dirty.
          Marco Pivetta made changes -
          Link This issue is referenced by DDC-3005 [ DDC-3005 ]
          Marco Pivetta made changes -
          Link This issue depends on DDC-250 [ DDC-250 ]
          Marco Pivetta made changes -
          Link This issue depends on DDC-250 [ DDC-250 ]
          Hide
          Marco Pivetta added a comment -

          Handled in DDC-3005 via DDC-3070

          Show
          Marco Pivetta added a comment - Handled in DDC-3005 via DDC-3070
          Marco Pivetta made changes -
          Status In Progress [ 3 ] Resolved [ 5 ]
          Fix Version/s 2.5 [ 10522 ]
          Fix Version/s 2.x [ 10090 ]
          Resolution Fixed [ 1 ]
          Marco Pivetta made changes -
          Assignee Benjamin Eberlei [ beberlei ] Marco Pivetta [ ocramius ]
          Marco Pivetta made changes -
          Labels association hydration listener postLoad
          Marco Pivetta made changes -
          Remote Link This issue links to "Merge Commit (Web Link)" [ 10277 ]

          This list may be incomplete, as errors occurred whilst retrieving source from linked applications:

          • Request to http://www.doctrine-project.org/fisheye/ failed: Error in remote call to 'FishEye 0 (http://www.doctrine-project.org/fisheye/)' (http://www.doctrine-project.org/fisheye) [AbstractRestCommand{path='/rest-service-fe/search-v1/crossRepositoryQuery', params={query=DDC-54, expand=changesets[0:20].revisions[0:29],reviews}, methodType=GET}] : Received status code 503 (Service Temporarily Unavailable)

            People

            • Assignee:
              Marco Pivetta
              Reporter:
              Roman S. Borschel
            • Votes:
              7 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: