Method getId() in generated proxy class casts to int, conflicts with enum primary key #7193

Open
opened 2026-01-22 15:46:24 +01:00 by admin · 0 comments
Owner

Originally created by @pauljura on GitHub (Jul 31, 2023).

Bug Report

Q A
BC Break no
Version 2.15.4 (encountered while on 2.14.0 but still present after updating to 2.15.4 today)

Summary

The generated proxy class for an entity has the following code for the getId() method:

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


        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getId', []);

        return parent::getId();
    }

The problem is the line with return (int) parent::getId(); because it's hardcoded to cast the return value to int, even though the method is expected to return an enum class.

Current behavior

An error is thrown:

Proxies\\__CG__\\App\\Entity\\ExampleEntity::getId(): Return value must be of type ?ExampleEnum, int returned

How to reproduce

To reproduce this, you need:

  1. an entity with a PHP enum class as the primary key
  2. a second entity that has a ManyToOne relationship with the first
  3. load an instance of the second entity, and then try to fetch the id of the related entity (the one with the enum PK)
  4. since the related entity is not yet loaded, the proxy method will be used
  5. error occurs
enum ExampleEnum: int
{
  Case A = 1;
  Case B = 2;
}

class ExampleEntity
{
  #[ORM\Column(name: 'id', type: Types::INTEGER, nullable: false, enumType: ExampleEnum::class)]
  #[ORM\Id]
  #[ORM\GeneratedValue(strategy: 'IDENTITY')]
  private ?ExampleEnum $id = null;

  public function getId(): ?ExampleEnum
  {
    return $this->id;
  }
}

class AnotherEntity
{
  #[ORM\Column(name: 'id', type: Types::INTEGER, nullable: false)]
  #[ORM\Id]
  #[ORM\GeneratedValue(strategy: 'IDENTITY')]
  private ?int $id = null;

  public function getId(): ?int
  {
    return $this->id;
  }

  #[ORM\ManyToOne(targetEntity: ExampleEntity::class)]
  #[ORM\JoinColumn(name: 'entityId', referencedColumnName: 'id', nullable: false)]
  private ExampleEntity $relatedEntity;

  public function getRelatedEntity: ExampleEntity
  {
    return $this->relatedEntity;
  }
}


$foo = $em->getRepository(AnotherEntity::class)->find(1);

$enum = $foo->getRelatedEntity()->getId(); // fails here

Expected behavior

The getId() method should return the correct enum class instead of an int.

Probably just removing the (int) should fix it.

Workaround

Avoid using the proxy by using eager loading, or fetching some other property to initialize the object.

Originally created by @pauljura on GitHub (Jul 31, 2023). ### Bug Report <!-- Fill in the relevant information below to help triage your issue. --> | Q | A |------------ | ------ | BC Break | no | Version | 2.15.4 (encountered while on 2.14.0 but still present after updating to 2.15.4 today) #### Summary The generated proxy class for an entity has the following code for the getId() method: ``` /** * {@inheritDoc} */ public function getId(): ?ExampleEnum { if ($this->__isInitialized__ === false) { return (int) parent::getId(); } $this->__initializer__ && $this->__initializer__->__invoke($this, 'getId', []); return parent::getId(); } ``` The problem is the line with `return (int) parent::getId();` because it's hardcoded to cast the return value to int, even though the method is expected to return an enum class. #### Current behavior An error is thrown: ``` Proxies\\__CG__\\App\\Entity\\ExampleEntity::getId(): Return value must be of type ?ExampleEnum, int returned ``` #### How to reproduce To reproduce this, you need: 1) an entity with a PHP enum class as the primary key 2) a second entity that has a ManyToOne relationship with the first 3) load an instance of the second entity, and then try to fetch the id of the related entity (the one with the enum PK) 4) since the related entity is not yet loaded, the proxy method will be used 5) error occurs ``` enum ExampleEnum: int { Case A = 1; Case B = 2; } class ExampleEntity { #[ORM\Column(name: 'id', type: Types::INTEGER, nullable: false, enumType: ExampleEnum::class)] #[ORM\Id] #[ORM\GeneratedValue(strategy: 'IDENTITY')] private ?ExampleEnum $id = null; public function getId(): ?ExampleEnum { return $this->id; } } class AnotherEntity { #[ORM\Column(name: 'id', type: Types::INTEGER, nullable: false)] #[ORM\Id] #[ORM\GeneratedValue(strategy: 'IDENTITY')] private ?int $id = null; public function getId(): ?int { return $this->id; } #[ORM\ManyToOne(targetEntity: ExampleEntity::class)] #[ORM\JoinColumn(name: 'entityId', referencedColumnName: 'id', nullable: false)] private ExampleEntity $relatedEntity; public function getRelatedEntity: ExampleEntity { return $this->relatedEntity; } } $foo = $em->getRepository(AnotherEntity::class)->find(1); $enum = $foo->getRelatedEntity()->getId(); // fails here ``` #### Expected behavior The getId() method should return the correct enum class instead of an int. Probably just removing the `(int)` should fix it. #### Workaround Avoid using the proxy by using eager loading, or fetching some other property to initialize the object.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7193