Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2556

Proxy getId() different code generated when using Trait

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Security Level: All
    • Labels:
      None

      Description

      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
      

        Activity

        Hide
        Marco Pivetta added a comment -

        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?

        Show
        Marco Pivetta added a comment - 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?
        Hide
        Eduardo Oliveira added a comment -

        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
        Show
        Eduardo Oliveira added a comment - 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
        Hide
        Marco Pivetta added a comment -

        Eduardo Oliveira 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());
        Show
        Marco Pivetta added a comment - Eduardo Oliveira 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());
        Hide
        Eduardo Oliveira added a comment - - edited
        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.

        Show
        Eduardo Oliveira added a comment - - edited 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.
        Hide
        Marco Pivetta added a comment -

        Eduardo Oliveira does this also happen with 2.3.x? (asking because the proxy generation logic was rewritten for 2.4)

        Show
        Marco Pivetta added a comment - Eduardo Oliveira does this also happen with 2.3.x? (asking because the proxy generation logic was rewritten for 2.4)
        Hide
        Eduardo Oliveira added a comment - - edited

        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();
            }
        
        Show
        Eduardo Oliveira added a comment - - edited 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(); }
        Hide
        Marco Pivetta added a comment -

        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.

        Show
        Marco Pivetta added a comment - 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.

          People

          • Assignee:
            Marco Pivetta
            Reporter:
            Eduardo Oliveira
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: