Property promotion not working correctly with associations/proxies #7253

Open
opened 2026-01-22 15:48:16 +01:00 by admin · 1 comment
Owner

Originally created by @delolmo on GitHub (Nov 20, 2023).

Bug Report

Q A
BC Break no
Version 2.17.1

Summary

I opened this #10456 in the past, hoping that it had been fixed in #10385, but I still keep getting the same error.

Given that associations are loaded through proxies, when using constructor promotion in entities, PHP will throw an error when trying to access a property of the proxy object.

Current behavior

The stated above.

How to reproduce

Given these entities (i.e.):


use Doctrine\ORM\Mapping as ORM;
use Ramsey\UuidInterface;

final class User 
{
      public function __construct(
            #[ORM\Id]
            #[ORM\Column(type: 'uuid_binary')]
            public UuidInterface $id,
            #[ORM\Column(type: 'string', unique: true)
            public string $username,
      ){
      }
}

final class Group
{
      public function __construct(
            #[ORM\Id]
            #[ORM\Column(type: 'uuid_binary')]
            public UuidInterface $id,
            #[ORM\Column(type: 'string', unique: true)
            public string $name,
      ){
      }
}

final readonly class Member
{
      public function __construct(
            #[ORM\Id]
            #[ORM\Column(type: 'uuid_binary')]
            public UuidInterface $id,
            #[ORM\ManyToOne(targetEntity: User::class)
            public User $user,
            #[ORM\ManyToOne(targetEntity: Group::class)
            public Group $group,
      ){
      }
}

One would expect this code to work:

$membersRepo = $entityManager->getRepository(Member::class);
$allMembers = $membersRepo->findAll();

foreach ($allMembers as $member) {
        print_r([$member->user->username, $member->group->name]);
}

But the following error is thrown:

PHP Fatal error:  Uncaught Error: Typed property User::$username must not be accessed before initialization in (...)

Expected behavior

If possible, no error should be thrown and properties should be initialized when trying to access the proxy object.

Originally created by @delolmo on GitHub (Nov 20, 2023). ### Bug Report | Q | A |------------ | ------ | BC Break | no | Version | 2.17.1 #### Summary I opened this #10456 in the past, hoping that it had been fixed in #10385, but I still keep getting the same error. Given that associations are loaded through proxies, when using constructor promotion in entities, PHP will throw an error when trying to access a property of the proxy object. #### Current behavior The stated above. #### How to reproduce Given these entities (i.e.): ```php use Doctrine\ORM\Mapping as ORM; use Ramsey\UuidInterface; final class User { public function __construct( #[ORM\Id] #[ORM\Column(type: 'uuid_binary')] public UuidInterface $id, #[ORM\Column(type: 'string', unique: true) public string $username, ){ } } final class Group { public function __construct( #[ORM\Id] #[ORM\Column(type: 'uuid_binary')] public UuidInterface $id, #[ORM\Column(type: 'string', unique: true) public string $name, ){ } } final readonly class Member { public function __construct( #[ORM\Id] #[ORM\Column(type: 'uuid_binary')] public UuidInterface $id, #[ORM\ManyToOne(targetEntity: User::class) public User $user, #[ORM\ManyToOne(targetEntity: Group::class) public Group $group, ){ } } ``` One would expect this code to work: ```php $membersRepo = $entityManager->getRepository(Member::class); $allMembers = $membersRepo->findAll(); foreach ($allMembers as $member) { print_r([$member->user->username, $member->group->name]); } ``` But the following error is thrown: ``` PHP Fatal error: Uncaught Error: Typed property User::$username must not be accessed before initialization in (...) ``` #### Expected behavior If possible, no error should be thrown and properties should be initialized when trying to access the proxy object.
Author
Owner

@delolmo commented on GitHub (Nov 23, 2023):

Just to continue with the example, this actually works (although it comes as no surprise):

$membersRepo = $entityManager->getRepository(Member::class);
$allMembers = $membersRepo->findAll();

foreach ($allMembers as $member) {
        $entityManager->refresh($user);
        $entityManager->refresh($group);
        print_r([$member->user->username, $member->group->name]);
}
@delolmo commented on GitHub (Nov 23, 2023): Just to continue with the example, this actually works (although it comes as no surprise): ```php $membersRepo = $entityManager->getRepository(Member::class); $allMembers = $membersRepo->findAll(); foreach ($allMembers as $member) { $entityManager->refresh($user); $entityManager->refresh($group); print_r([$member->user->username, $member->group->name]); } ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7253