Question: how to map two entities who's IDs are also columns #5392

Open
opened 2026-01-22 15:06:15 +01:00 by admin · 3 comments
Owner

Originally created by @yogi5642 on GitHub (Jan 24, 2017).

I was trying to use Doctrine to add a layer of sense on a legacy database, and the table structure I'm having trouble with looks like this:

members

  • phone_number
  • name

attendee

  • phone_number
  • temporary_details

An attendee can but may not always be a member.

So with a Mapping something like:

/**
 * @ORM\Table(name="members")
 */
class Member
{
    /**
     * @var string
     *
     * @ORM\Column(name="phone_number", type="string", length=10, nullable=false)
     * @ORM\Id
     */
    private $phoneNumber;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=15, nullable=true)
     */
    private $name;

    /**
     * @var Attendee
     *
     * @ORM\OneToOne(targetEntity="Attendee", inversedBy="Member",fetch="EAGER")
     * @ORM\joinColumn(name="phone_number", referencedColumnName="phone_number")
     */
    private $attendee;


    public function __construct($phoneNumber)
    {
        $this->phoneNumber = $phoneNumber;
    }
}
/**
 * @ORM\Table(name="attendee")
 */
class Attendee
{
    /**
     * @var string
     *
     * @ORM\Column(name="phone_number", type="string", length=10, nullable=false)
     * @ORM\Id
     */
    private $phoneNumber;

    /**
     * @var string
     *
     * @ORM\Column(name="temporary_details", type="string", length=15, nullable=true)
     */
    private $tempDetails;

    /**
     * @var Member
     *
     * @ORM\OneToOne(targetEntity="Member", inversedBy="Atendee",fetch="EAGER")
     * @ORM\joinColumn(name="phone_number", referencedColumnName="phone_number")
     */
    private $member;

}

I'm in trouble because I can't create a Member like so:

$member = new Member('+123456');
$em->persist($member);
$em->flush();

As the Member mapping using the phone_number, so when Doctrine tries to manage this relationship, seeing that it's persisting a Member with no Attendee, maps the Atendee join coulumn (the phone_number) to null, instead of what was provided.

It's https://github.com/doctrine/doctrine2/blob/v2.5.6/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php#L669 where the joined entity id is overwriting the specicied id, but I guess this is correct functionality.

Any suggestions on how to map this better to overcome this? I can't change this database.

Originally created by @yogi5642 on GitHub (Jan 24, 2017). I was trying to use Doctrine to add a layer of sense on a legacy database, and the table structure I'm having trouble with looks like this: members - phone_number - name attendee - phone_number - temporary_details An attendee can but may not always be a member. So with a Mapping something like: ```php /** * @ORM\Table(name="members") */ class Member { /** * @var string * * @ORM\Column(name="phone_number", type="string", length=10, nullable=false) * @ORM\Id */ private $phoneNumber; /** * @var string * * @ORM\Column(name="name", type="string", length=15, nullable=true) */ private $name; /** * @var Attendee * * @ORM\OneToOne(targetEntity="Attendee", inversedBy="Member",fetch="EAGER") * @ORM\joinColumn(name="phone_number", referencedColumnName="phone_number") */ private $attendee; public function __construct($phoneNumber) { $this->phoneNumber = $phoneNumber; } } ``` ```php /** * @ORM\Table(name="attendee") */ class Attendee { /** * @var string * * @ORM\Column(name="phone_number", type="string", length=10, nullable=false) * @ORM\Id */ private $phoneNumber; /** * @var string * * @ORM\Column(name="temporary_details", type="string", length=15, nullable=true) */ private $tempDetails; /** * @var Member * * @ORM\OneToOne(targetEntity="Member", inversedBy="Atendee",fetch="EAGER") * @ORM\joinColumn(name="phone_number", referencedColumnName="phone_number") */ private $member; } ``` I'm in trouble because I can't create a Member like so: ```php $member = new Member('+123456'); $em->persist($member); $em->flush(); ``` As the Member mapping using the phone_number, so when Doctrine tries to manage this relationship, seeing that it's persisting a Member with no Attendee, maps the Atendee join coulumn (the phone_number) to null, instead of what was provided. It's https://github.com/doctrine/doctrine2/blob/v2.5.6/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php#L669 where the joined entity id is overwriting the specicied id, but I guess this is correct functionality. Any suggestions on how to map this better to overcome this? I can't change this database.
Author
Owner

@Ocramius commented on GitHub (Jan 24, 2017):

We don't support mapping a field to both an association and a scalar value: it has to be one of the two.

I think the devil is in the details here. Your sentence is a bit ambiguous:

An attendee can but may not always be a member.

This is unclear to me: are you maybe describing an ISA association? Maybe this should be a joined table inheritance?

@Ocramius commented on GitHub (Jan 24, 2017): We don't support mapping a field to both an association and a scalar value: it has to be one of the two. I think the devil is in the details here. Your sentence is a bit ambiguous: > An attendee can but may not always be a member. This is unclear to me: are you maybe describing an ISA association? Maybe this should be a joined table inheritance?
Author
Owner

@yogi5642 commented on GitHub (Jan 25, 2017):

Thanks for taking the time to comment on this, much appreciated :)

It's this

We don't support mapping a field to both an association and a scalar value: it has to be one of the two.

That I suspected, but couldn't find explicitly mentioned in the docs. Perhaps Doctrine could error when defining an entity like this if it is truly unsupported?

As far as I can tell, using joined table inheritance would still render me unable to make use of the scalar value if that field is also used for the join. Also, in this example an Attendee may exist, who does not inherit from a Member, so it doesn't seem like joined table inheritance at would work here.

The only solution I can think of would be to join the entities outside of Doctrine's automatic associations.

Thanks!

@yogi5642 commented on GitHub (Jan 25, 2017): Thanks for taking the time to comment on this, much appreciated :) It's this > We don't support mapping a field to both an association and a scalar value: it has to be one of the two. That I suspected, but couldn't find explicitly mentioned in the docs. Perhaps Doctrine could error when defining an entity like this if it is truly unsupported? As far as I can tell, using joined table inheritance would still render me unable to make use of the scalar value if that field is also used for the join. Also, in this example an `Attendee` may exist, who does not inherit from a `Member`, so it doesn't seem like joined table inheritance at would work here. The only solution I can think of would be to join the entities outside of Doctrine's automatic associations. Thanks!
Author
Owner

@Ocramius commented on GitHub (Jan 25, 2017):

That I suspected, but couldn't find explicitly mentioned in the docs. Perhaps Doctrine could error when defining an entity like this if it is truly unsupported?

It's something we're working on for 3.x

@Ocramius commented on GitHub (Jan 25, 2017): > That I suspected, but couldn't find explicitly mentioned in the docs. Perhaps Doctrine could error when defining an entity like this if it is truly unsupported? It's something we're working on for 3.x
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5392