Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-1010

Crash when fetching results from qb inside postLoad event

    Details

    • Type: Documentation Documentation
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 2.0.1
    • Fix Version/s: 2.4
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None
    • Environment:
      PHP 5.3.3-1ubuntu9.3
      KUbuntu 10.10

      Description

      I registered an event listener to my entity manager and on a postLoad event, I want to prepare some data in a nice way (fetch translations for my library + store into associative array into entity). Here's my snippet:

      class TranslationListener implements EventSubscriber
      {
          public function getSubscribedEvents()
          {
              return array(Events::postLoad);
          }
      
          public function postLoad(LifecycleEventArgs $args)
          {
              $em = $args->getEntityManager();
              $entity = $args->getEntity();
      
              if ($entity instanceof Lib) {
                  $qb = $em->createQueryBuilder();
                  $qb = $qb->select('T')->from('Translate', 'T')->join('T.locale', 'TT')->where('T.lib = ?1')->setParameter(1, $entity->idLib);
                  $res = $qb->getQuery()->getResult();
                  foreach ($res as $tr) {
                      $entity->tr[$tr->locale->idLocale] = $tr;
                  }
              }
          }
      }
      

      When this code is run (eg. getting the Library objects), I got a crash where getResult() is called:

      Fatal error: Call to a member function fetch() on a non-object in /home/thepianoguy/testproject/trunk/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php on line 126
      Call Stack
      #	Time	Memory	Function	Location
      1	0.0004	656080	{main}( )	../index.php:0
      2	0.1081	18760176	TApplication->run( )	../index.php:48
      3	0.2637	33817288	TApplication->runService( )	../TApplication.php:382
      4	0.2637	33817288	TPageService->run( )	../TApplication.php:1095
      5	0.2698	34788448	TPageService->runPage( )	../TPageService.php:444
      6	0.2715	34986768	TPage->run( )	../TPageService.php:498
      7	0.2716	34989128	TPage->processNormalRequest( )	../TPage.php:198
      8	0.3383	42770128	TControl->loadRecursive( )	../TPage.php:215
      9	0.3383	42770208	ContactUserAddEdit->onLoad( )	../TControl.php:1286
      10	0.3383	42771912	ContactUserAddEdit->loadData( )	../ContactUserAddEdit.php:56
      11	0.3452	43436904	Doctrine\ORM\AbstractQuery->getResult( )	../ContactUserAddEdit.php:124
      12	0.3452	43437296	Doctrine\ORM\AbstractQuery->execute( )	../AbstractQuery.php:366
      13	0.4160	47009328	Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll( )	../AbstractQuery.php:537
      14	0.4160	47011504	Doctrine\ORM\Internal\Hydration\ObjectHydrator->_hydrateAll( )	../AbstractHydrator.php:99
      

      If I comment the line 137 in Doctrine/ORM/Internal/Hydration/AbstractHydrator in _cleanup(), my code works fine:
      // $this->_stmt = null;

      I think there is a problem when using alredy used entity manager and query builder inside the postLoad event.

        Activity

        Matevz Jekovec created issue -
        Hide
        Benjamin Eberlei added a comment -

        The hydrator is reused internally, this is potentially dangerous as I figure from your use-case.

        Show
        Benjamin Eberlei added a comment - The hydrator is reused internally, this is potentially dangerous as I figure from your use-case.
        Benjamin Eberlei made changes -
        Field Original Value New Value
        Description I registered an event listener to my entity manager and on a postLoad event, I want to prepare some data in a nice way (fetch translations for my library + store into associative array into entity). Here's my snippet:

        class TranslationListener implements EventSubscriber
        {
            public function getSubscribedEvents()
            {
                return array(Events::postLoad);
            }

            public function postLoad(LifecycleEventArgs $args)
            {
                $em = $args->getEntityManager();
                $entity = $args->getEntity();

                if ($entity instanceof Lib) {
                    $qb = $em->createQueryBuilder();
                    $qb = $qb->select('T')->from('Translate', 'T')->join('T.locale', 'TT')->where('T.lib = ?1')->setParameter(1, $entity->idLib);
                    $res = $qb->getQuery()->getResult();
                    foreach ($res as $tr) {
                        $entity->tr[$tr->locale->idLocale] = $tr;
                    }
                }
            }
        }

        When this code is run (eg. getting the Library objects), I got a crash where getResult() is called:
        Fatal error: Call to a member function fetch() on a non-object in /home/thepianoguy/testproject/trunk/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php on line 126
        Call Stack
        # Time Memory Function Location
        1 0.0004 656080 {main}( ) ../index.php:0
        2 0.1081 18760176 TApplication->run( ) ../index.php:48
        3 0.2637 33817288 TApplication->runService( ) ../TApplication.php:382
        4 0.2637 33817288 TPageService->run( ) ../TApplication.php:1095
        5 0.2698 34788448 TPageService->runPage( ) ../TPageService.php:444
        6 0.2715 34986768 TPage->run( ) ../TPageService.php:498
        7 0.2716 34989128 TPage->processNormalRequest( ) ../TPage.php:198
        8 0.3383 42770128 TControl->loadRecursive( ) ../TPage.php:215
        9 0.3383 42770208 ContactUserAddEdit->onLoad( ) ../TControl.php:1286
        10 0.3383 42771912 ContactUserAddEdit->loadData( ) ../ContactUserAddEdit.php:56
        11 0.3452 43436904 Doctrine\ORM\AbstractQuery->getResult( ) ../ContactUserAddEdit.php:124
        12 0.3452 43437296 Doctrine\ORM\AbstractQuery->execute( ) ../AbstractQuery.php:366
        13 0.4160 47009328 Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll( ) ../AbstractQuery.php:537
        14 0.4160 47011504 Doctrine\ORM\Internal\Hydration\ObjectHydrator->_hydrateAll( ) ../AbstractHydrator.php:99

        If I comment the line 137 in Doctrine/ORM/Internal/Hydration/AbstractHydrator in _cleanup(), my code works fine:
        // $this->_stmt = null;

        I think there is a problem when using alredy used entity manager and query builder inside the postLoad event.
        I registered an event listener to my entity manager and on a postLoad event, I want to prepare some data in a nice way (fetch translations for my library + store into associative array into entity). Here's my snippet:

        {code}
        class TranslationListener implements EventSubscriber
        {
            public function getSubscribedEvents()
            {
                return array(Events::postLoad);
            }

            public function postLoad(LifecycleEventArgs $args)
            {
                $em = $args->getEntityManager();
                $entity = $args->getEntity();

                if ($entity instanceof Lib) {
                    $qb = $em->createQueryBuilder();
                    $qb = $qb->select('T')->from('Translate', 'T')->join('T.locale', 'TT')->where('T.lib = ?1')->setParameter(1, $entity->idLib);
                    $res = $qb->getQuery()->getResult();
                    foreach ($res as $tr) {
                        $entity->tr[$tr->locale->idLocale] = $tr;
                    }
                }
            }
        }
        {code}

        When this code is run (eg. getting the Library objects), I got a crash where getResult() is called:

        {code}
        Fatal error: Call to a member function fetch() on a non-object in /home/thepianoguy/testproject/trunk/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php on line 126
        Call Stack
        # Time Memory Function Location
        1 0.0004 656080 {main}( ) ../index.php:0
        2 0.1081 18760176 TApplication->run( ) ../index.php:48
        3 0.2637 33817288 TApplication->runService( ) ../TApplication.php:382
        4 0.2637 33817288 TPageService->run( ) ../TApplication.php:1095
        5 0.2698 34788448 TPageService->runPage( ) ../TPageService.php:444
        6 0.2715 34986768 TPage->run( ) ../TPageService.php:498
        7 0.2716 34989128 TPage->processNormalRequest( ) ../TPage.php:198
        8 0.3383 42770128 TControl->loadRecursive( ) ../TPage.php:215
        9 0.3383 42770208 ContactUserAddEdit->onLoad( ) ../TControl.php:1286
        10 0.3383 42771912 ContactUserAddEdit->loadData( ) ../ContactUserAddEdit.php:56
        11 0.3452 43436904 Doctrine\ORM\AbstractQuery->getResult( ) ../ContactUserAddEdit.php:124
        12 0.3452 43437296 Doctrine\ORM\AbstractQuery->execute( ) ../AbstractQuery.php:366
        13 0.4160 47009328 Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll( ) ../AbstractQuery.php:537
        14 0.4160 47011504 Doctrine\ORM\Internal\Hydration\ObjectHydrator->_hydrateAll( ) ../AbstractHydrator.php:99
        {code}

        If I comment the line 137 in Doctrine/ORM/Internal/Hydration/AbstractHydrator in _cleanup(), my code works fine:
        // $this->_stmt = null;

        I think there is a problem when using alredy used entity manager and query builder inside the postLoad event.
        Hide
        Benjamin Eberlei added a comment -

        A workaround is to re-registr the object hydrator under a new name

        $configuration->setHydrationMode("object2", "Doctrine\ORM\Internal\Hydration\ObjectHydrator");
        

        and use it in your query.

        $query->setHydrationMode("object2");
        
        Show
        Benjamin Eberlei added a comment - A workaround is to re-registr the object hydrator under a new name $configuration->setHydrationMode( "object2" , "Doctrine\ORM\Internal\Hydration\ObjectHydrator" ); and use it in your query. $query->setHydrationMode( "object2" );
        Benjamin Eberlei made changes -
        Workflow jira [ 12342 ] jira-feedback [ 13906 ]
        Benjamin Eberlei made changes -
        Workflow jira-feedback [ 13906 ] jira-feedback2 [ 15770 ]
        Benjamin Eberlei made changes -
        Workflow jira-feedback2 [ 15770 ] jira-feedback3 [ 18027 ]
        Hide
        Marco Pivetta added a comment -

        Marking as documentation issue, since the user has to be warned that `postLoad` has to use a dedicated hydrator to execute more load operations.

        Show
        Marco Pivetta added a comment - Marking as documentation issue, since the user has to be warned that `postLoad` has to use a dedicated hydrator to execute more load operations.
        Marco Pivetta made changes -
        Issue Type Bug [ 1 ] Documentation [ 6 ]
        Priority Major [ 3 ] Minor [ 4 ]
        Hide
        Guilherme Blanco added a comment -
        Show
        Guilherme Blanco added a comment - I fixed this issue in master as of https://github.com/doctrine/doctrine2/commit/8d13601e39d0fdefdd1d2c0a85704c440b8bdd37 Cheers, GB
        Guilherme Blanco made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Guilherme Blanco made changes -
        Assignee Benjamin Eberlei [ beberlei ] Guilherme Blanco [ guilhermeblanco ]
        Guilherme Blanco made changes -
        Status Resolved [ 5 ] Closed [ 6 ]
        Benjamin Eberlei made changes -
        Resolution Fixed [ 1 ]
        Status Closed [ 6 ] Reopened [ 4 ]
        Benjamin Eberlei made changes -
        Status Reopened [ 4 ] Resolved [ 5 ]
        Fix Version/s 2.4 [ 10321 ]
        Resolution Fixed [ 1 ]

        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-1010, expand=changesets[0:20].revisions[0:29],reviews}, methodType=GET}] : Received status code 503 (Service Temporarily Unavailable)

          People

          • Assignee:
            Guilherme Blanco
            Reporter:
            Matevz Jekovec
          • Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: