Skip to content

Loading…

DDC-2556: Proxy getId() different code generated when using Trait #3282

Open
doctrinebot opened this Issue · 9 comments

2 participants

@doctrinebot

Jira issue originally created by user entering:

class Timezone {
    /****
     * @var integer
     *
     * @ORM\Column(name="id", type="smallint", nullable=false, options={"unsigned": true})
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /****
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }
}

If I replace that code with a Trait with equal code and use it on the entity the proxy will be generated different.

Without trait:

    /****
     * {@inheritDoc}
     */
    public function getId()
    {
        if ($this->*_isInitialized_* === false) {
            return (int)  parent::getId();
        }


        $this->*_initializer__ && $this->__initializer__->_*invoke($this, 'getId', array());

        return parent::getId();
    }

With trait:

    /****
     * {@inheritDoc}
     */
    public function getId()
    {

        $this->*_initializer__ && $this->__initializer__->_*invoke($this, 'getId', array());

        return parent::getId();
    }

And in this code:

$timezone = $this->timezoneRepository->findReadOnly(
    $campaign->getTimezone()->getId()
);

I get:
Doctrine\ORM\ORMException: The identifier id is missing for a query of EB\Core\KernelBundle\Entity\Common\Timezone

$campaign->getTimezone()->getId()
Is returning null.

About the findReadOnly is just a wrapper that will fetch from cache if not there fetch from DB, anyway if I change it to find() exact same problem

My versions of doctrine:

$ php composer.phar show -i | grep doctrine
doctrine/annotations                   v1.1.2             Docblock Annotations Parser
doctrine/cache                         v1.0               Caching library offering an object-oriented API for many cache backends
doctrine/collections                   v1.1               Collections Abstraction library
doctrine/common                        2.4.0-RC4          Common Library for Doctrine projects
doctrine/data-fixtures                 dev-master 6924952 Data Fixtures for all Doctrine Object Managers
doctrine/dbal                          2.4.0-RC2          Database Abstraction Layer
doctrine/doctrine-bundle               v1.2.0             Symfony DoctrineBundle
doctrine/doctrine-fixtures-bundle      dev-master 512fc0f Symfony DoctrineFixturesBundle
doctrine/doctrine-migrations-bundle    dev-master 5fc1167 Symfony DoctrineMigrationsBundle
doctrine/inflector                     v1.0               Common String Manipulations with regard to casing and singular/plural rules.
doctrine/lexer                         v1.0               Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations                    dev-master ced3b41 Database Schema migrations using Doctrine DBAL
doctrine/orm                           2.4.0-RC2          Object-Relational-Mapper for PHP
gedmo/doctrine-extensions              v2.3.6             Doctrine2 behavioral extensions
stof/doctrine-extensions-bundle        dev-master 6577f23 Integration of the gedmo/doctrine-extensions with Symfony2
@doctrinebot

Comment created by @ocramius:

Is the problem here the repository or just the trait method?

Can you please clean up the issue to insulate only the affected part? What is getId returning on that kind of object?

@doctrinebot

Comment created by entering:

Marco I will try to do better, I will try to do make a test case that proves this.

But i can leave here already more info:

  • There is an entity Campaign that have a Timezone (ManyToOne in Campaign side);
  • This entity Campaign is fetch (with lazy in all associations) and serialized and put in cache;
  • This entity Campaign don't have timezone itself, but $campaign->getTimezone()->getId() hit the return (int) parent::getId(); on proxy not making any query to get the timezone, in the case with trait the proxy code is different and it returns null
@doctrinebot

Comment created by @ocramius:

[~entering] is the proxy in a detached state when you do this? What happens if (with an existing identifier) you do following?

var_dump($entityManager->getReference('Timezone', 123)->getId());

@doctrinebot

Comment created by entering:

var_dump ( $this->timezoneRepository->getEM()->getReference('EBCoreKernelBundle:Common\Timezone', 1)->getId() ); // 1

Marco yes is on detached mode, and I know that, I'm relying on the proxy to get the ID, because I don't want any queries being "issued", so I'm doing like

$campaign = $campaignRepository->findReadOnly(10); // hit cache

$timezoneRepository->findReadOnly($campaign->getTimezone()->getId() /** rely on proxy **/); // hit memcache

This just work in the last versions of Doctrine that have lazy getId(), but it looks that for traits something wrong happens on the generation of Proxy.

If on Entity timezone I use the trait but override the getId() everything works perfect again.

@doctrinebot

Comment created by @ocramius:

[~entering] does this also happen with 2.3.x? (asking because the proxy generation logic was rewritten for 2.4)

@doctrinebot

Comment created by entering:

2.3 the proxy is quite different but the essence of the problem remains:

Proxy with trait (doesn't work, because as far as I know will try to make a query in detach mode):

    public function getId()
    {
        $this->**load();
        return parent::getId();
    }

Proxy without trait (works well):

    public function getId()
    {
        if ($this->*_isInitialized_* === false) {
            return (int) $this->_identifier["id"];
        }
        $this->**load();
        return parent::getId();
    }
@doctrinebot

Comment created by @ocramius:

Ok, so at least I now know it's not an issue with the upgrade, but it was also borked before. Thanks for following along till here: I'll work on a patch as soon as I have time.

@doctrinebot

Comment created by tPl0ch:

@ocramius

This just got a little bit hotter for us. We moved all our ID related code into a trait that is shared by most our entities. After deploying that we saw a dramatic rise in small id based queries to the database, which is related to this bug here.

We had to revert the changes for now, but I'd be happy to work on a fix if there still is a need.

Regards
Thomas

@Ocramius Ocramius was assigned by doctrinebot
@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.