Cannot assign <IdClass> to property of type <EntityClass>

I have the following entity graph:

#[ORM\Entity]
class Professional
{
    #[ORM\Id]
    #[ORM\Column(type: 'professional_id')]
    #[ORM\GeneratedValue(strategy: 'NONE')]
    private ProfessionalId $id;

    #[ORM\OneToOne(targetEntity: ProfessionalCatchmentArea::class, mappedBy: 'professional', cascade: ['all'])]
    private ?ProfessionalCatchmentArea $catchmentArea = null;
}
#[ORM\Entity]
class ProfessionalCatchmentArea
{
    #[ORM\Id]
    #[ORM\OneToOne(targetEntity: Professional::class, inversedBy: 'catchmentArea')]
    #[ORM\JoinColumn(nullable: false)]
    private Professional $professional;

    #[ORM\OneToMany(targetEntity: ProfessionalCatchmentAreaZone::class, mappedBy: 'catchmentArea', orphanRemoval: true, cascade: ['all'])]
    private Collection $zones;
}
#[ORM\Entity]
class ProfessionalCatchmentAreaZone
{
    #[ORM\Id]
    #[ORM\Column(type: 'uuid')]
    #[ORM\GeneratedValue(strategy: 'NONE')]
    private Uuid $id;

    #[ORM\ManyToOne(targetEntity: ProfessionalCatchmentArea::class, inversedBy: 'zones')]
    #[ORM\JoinColumn(name: 'professional_id', referencedColumnName: 'professional_id', nullable: false)]
    private ProfessionalCatchmentArea $catchmentArea;
}

Note: ProfessionalId is a custom ID class containing a UUID.

As you can see, Professional has a one-to-one relationship with ProfessionalCatchmentArea, which in turn has a one-to-many relationship with ProfessionalCatchmentAreaZone.

Due to the one-to-one, ProfessionalCatchmentArea shares its primary key with Professional.

Therefore, the JoinColumn for the many-to-one relationship from ProfessionalCatchmentAreaZone to ProfessionalCatchmentArea is based on the professional_id column.

For some reason, even though Doctrine does not complain with this mapping (bin/console doctrine:schema:validate is OK), and even though traversal from Professional to $catchmentArea to $zones works fine, attempting to load the ProfessionalCatchmentAreaZone entities directly from the EntityRepository fails:

$entityManager->getRepository(ProfessionalCatchmentAreaZone::class)->findAll();

Cannot assign App\Entity\ProfessionalId to property App\Entity\ProfessionalCatchmentArea::$professional of type App\Entity\Professional

Any idea why?

Is this mapping one-to-one => one-to-many, while sharing the primary key in the one-to-one relationship, not supported? Is this a Doctrine bug?


Solution 1:

I've got a few ideas:

  1. Based on the information provided, I'm inclined to believe this is an issue with the object inheritance and the mapped type for the data type of Professional->$id.

    Given that ProfessionalId extends the UUID, the only valid class datatype for ProfessionalId is the class ProfessionalId.

    If the data type was UUID then the values that are compatible with UUID would be an instance of UUID or ProfessionalId (because it INHERITS UUID).

  2. Check that the Datatype is registered for that name:

    <?php
    
    // In your bootstrap file
    
    \Doctrine\DBAL\Types\Type::addType('professional_id', ProfessionalId::class);
    
    ?>
    
  3. Ensure that the ProfessionalId type inherits the annotations from the UUID type as seen here:

    https://stackoverflow.com/a/40442063/5779200