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

          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.
          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
          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.
          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.
          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

            People

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

              Dates

              • Created:
                Updated:
                Resolved: