Skip to content

Loading…

DDC-456: Wrong implementation of loading metadata from cache #4958

Closed
doctrinebot opened this Issue · 12 comments

1 participant

@doctrinebot

Jira issue originally created by user else:

Dear developers,
There's a bug on line starting with 146 of ClassMetadataFactory.php, which loaded only one element in _loadedMetadata if cache is enable and it cause problem when you use inheritance.

 if ($this->_cacheDriver {
                if (($cached = $this->_cacheDriver->fetch("$realClassName\$CLASSMETADATA")) !== false) {

                    $this->_loadedMetadata[$realClassName] = $cached;                // if it's found in cache it load only one element
                } else {
                    foreach ($this->_loadMetadata($realClassName) as $loadedClassName) {
                        $this->_cacheDriver->save(
                            "$loadedClassName\$CLASSMETADATA", $this->_loadedMetadata[$loadedClassName], null
                        );
                    }
                }
            } else {
                $this->*loadMetadata($realClassName);                                         // if cache is not enable same block load more element to *loadMetadata
            }

hope you undestand

@doctrinebot

Comment created by romanb:

No, I dont understand. Where is the bug? What is the error? What about a testcase?

You say "it cause problem", what problem? Any error message or exception?

@doctrinebot

Comment created by else:

I'll try to explain it in detait.

lets say that ShopCustomer extends ShopGuest

1) You need get ShopCustomer metadata so for first time when you have nothing cache and block with foreach {} is called where $this->_loadMetadata() fills _metadata[] with all needed class ($_loadedMetadata[Shop_Customer] and $_loadedMetadata[Shop_Guest]) and cache with keys Shop_Customer\$CLASSMETADATA and ShopGuest\$CLASSMETADATA is set.

2) For the second time you need get ShopCustomer metadata again. But because you find Shop_Customer\$CLASSMETADATA on second line in cache and ONLY _loadedMetadata[Shop_Customer] will be loaded. So $_loadedMetadata[ShopGuest] is not loaded in difference with first case.

Then when you have in class ShopGuest defined variable @id you'll get Exception with message "Property id does not exist" on $em->createQuery("SELECT u FROM ShopCustomer where u.id = 1") for example.

It's too complicated because of using cache to demonstrate this error on testcases for me . I'm sorry.

@doctrinebot

Comment created by romanb:

Is Shop_Guest a mapped superclass and is the ID field private? Maybe this is the same as DDC-388 ?

Please attach your ShopGuest and ShopCustomer classes and mapping.

The problem is not in the caching code. The procedure you describe is correct, but the error should of course not happen if everything is mapped correctly.

@doctrinebot

Comment created by romanb:

Also, you said "you'll get Exception with message "Property id does not exist"" . Please show the full stack trace of the exception!

@doctrinebot

Comment created by else:

Hey Roman, i'm completely drunk so i'll write you tomorrow :-) don't you mind ?

@doctrinebot

Comment created by else:

You know ... another time in here... 4am :-)

@doctrinebot

Comment created by else:

I little more sober;-)

 Message:
Property id does not exist

Request Parameters:
array ( 'language' => 'cs', 'module' => 'default', 'controller' => 'index', 'action' => 'index', )

Exception trace vardump:

array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/ORM/Mapping/ClassMetadata.php' (length=76)
  'line' => int 344
  'function' => string 'getProperty' (length=11)
  'class' => string 'ReflectionClass' (length=15)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => string 'id' (length=2)


array
  'function' => string '**wakeup' (length=8)
  'class' => string 'Doctrine\ORM\Mapping\ClassMetadata' (length=34)
  'type' => string '->' (length=2)
  'args' => 
    array
      empty


array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/Common/Cache/ApcCache.php' (length=72)
  'line' => int 58
  'function' => string 'apc_fetch' (length=9)
  'args' => 
    array
      0 => string 'Shop*Data_Entity*Guest$CLASSMETADATA' (length=36)


array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/Common/Cache/AbstractCache.php' (length=77)
  'line' => int 59
  'function' => string '_doFetch' (length=8)
  'class' => string 'Doctrine\Common\Cache\ApcCache' (length=30)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => string 'Shop*Data_Entity*Guest$CLASSMETADATA' (length=36)


array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/ORM/Mapping/ClassMetadataFactory.php' (length=83)
  'line' => int 147
  'function' => string 'fetch' (length=5)
  'class' => string 'Doctrine\Common\Cache\AbstractCache' (length=35)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => string 'Shop*Data_Entity*Guest$CLASSMETADATA' (length=36)


array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/ORM/EntityManager.php' (length=68)
  'line' => int 206
  'function' => string 'getMetadataFor' (length=14)
  'class' => string 'Doctrine\ORM\Mapping\ClassMetadataFactory' (length=41)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => string 'Shop*Data_Entity*Guest' (length=22)


array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php' (length=88)
  'line' => int 66
  'function' => string 'getClassMetadata' (length=16)
  'class' => string 'Doctrine\ORM\EntityManager' (length=26)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => string 'Shop*Data_Entity*Guest' (length=22)


array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php' (length=90)
  'line' => int 101
  'function' => string '_prepare' (length=8)
  'class' => string 'Doctrine\ORM\Internal\Hydration\ObjectHydrator' (length=46)
  'type' => string '->' (length=2)
  'args' => 
    array
      empty


array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/ORM/AbstractQuery.php' (length=68)
  'line' => int 522
  'function' => string 'hydrateAll' (length=10)
  'class' => string 'Doctrine\ORM\Internal\Hydration\AbstractHydrator' (length=48)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => 
        object(Doctrine\DBAL\Driver\PDOStatement)[142]
          ...
      1 => 
        object(Doctrine\ORM\Query\ResultSetMapping)[140]
          ...
      2 => 
        array
          ...


array
  'file' => string '/home/else/workspace/Shop/www/library/Doctrine/ORM/AbstractQuery.php' (length=68)
  'line' => int 349
  'function' => string 'execute' (length=7)
  'class' => string 'Doctrine\ORM\AbstractQuery' (length=26)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => 
        array
          ...
      1 => int 1


array
  'file' => string '/home/else/workspace/Shop/www/library/Shop/Auth.php' (length=51)
  'line' => int 75
  'function' => string 'getResult' (length=9)
  'class' => string 'Doctrine\ORM\AbstractQuery' (length=26)
  'type' => string '->' (length=2)
  'args' => 
    array
      empty


array
  'file' => string '/home/else/workspace/Shop/www/application/controllers/IndexController.php' (length=73)
  'line' => int 30
  'function' => string 'getUser' (length=7)
  'class' => string 'Shop_Auth' (length=9)
  'type' => string '->' (length=2)
  'args' => 
    array
      empty


array
  'file' => string '/home/else/workspace/Shop/www/library/Zend/Controller/Action.php' (length=64)
  'line' => int 513
  'function' => string 'indexAction' (length=11)
  'class' => string 'IndexController' (length=15)
  'type' => string '->' (length=2)
  'args' => 
    array
      empty


array
  'file' => string '/home/else/workspace/Shop/www/library/Zend/Controller/Dispatcher/Standard.php' (length=77)
  'line' => int 289
  'function' => string 'dispatch' (length=8)
  'class' => string 'Zend*Controller*Action' (length=22)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => string 'indexAction' (length=11)


array
  'file' => string '/home/else/workspace/Shop/www/library/Zend/Controller/Front.php' (length=63)
  'line' => int 954
  'function' => string 'dispatch' (length=8)
  'class' => string 'Zend*Controller_Dispatcher*Standard' (length=35)
  'type' => string '->' (length=2)
  'args' => 
    array
      0 => 
        object(Zend*Controller_Request*Http)[86]
          ...
      1 => 
        object(Zend*Controller_Response*Http)[87]
          ...


array
  'file' => string '/home/else/workspace/Shop/www/library/Zend/Application/Bootstrap/Bootstrap.php' (length=78)
  'line' => int 97
  'function' => string 'dispatch' (length=8)
  'class' => string 'Zend*Controller*Front' (length=21)
  'type' => string '->' (length=2)
  'args' => 
    array
      empty


array
  'file' => string '/home/else/workspace/Shop/www/library/Zend/Application.php' (length=58)
  'line' => int 366
  'function' => string 'run' (length=3)
  'class' => string 'Zend*Application_Bootstrap*Bootstrap' (length=36)
  'type' => string '->' (length=2)
  'args' => 
    array
      empty


array
  'file' => string '/home/else/workspace/Shop/www/public/index.php' (length=46)
  'line' => int 14
  'function' => string 'run' (length=3)
  'class' => string 'Zend_Application' (length=16)
  'type' => string '->' (length=2)
  'args' => 
    array
      empty

@doctrinebot

Comment created by romanb:

Looks like the same as DDC-388.

@doctrinebot

Comment created by else:

Dear roman,

I don't understand explanation from DDC-388 very well. It's obvious that you get another results on first (without cache) and second (with cache) case. So where is the problem?

Andy

@doctrinebot

Comment created by romanb:

Fixed in http://github.com/doctrine/doctrine2/commit/d4232d906e433b1fe4dd8aa85aa7a4aca3a2cf4c .
Make sure to clear the metadata cache if necessary.

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot doctrinebot added this to the 2.0-BETA1 milestone
@doctrinebot doctrinebot closed this
@doctrinebot doctrinebot added the Bug label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.