Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to establish one-to-one relation through IDs between doctrine entities

I was hoping this be a straight forward process but it seems Doctrine doesn't really like the idea of linking entities through their IDs.

All I intended to do was normalising a table by shipping some fields from it to a new table and instead of adding a new reference field to the original table to hold the ID of the new corresponding record in the, make sure the new record in the child table will have identical ID to its parent row.

Here is an example of what I have:

A User entity, with annotated field $user to reference column ID in the UserDetail entity to itself's ID

/**
 * @ORM\Table(name="user", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
 * @ORM\Entity
 */
class User extends Entity
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id

     /**
      * @ORM\OneToOne(targetEntity="UserDetail", cascade={"persist"})
      * @ORM\JoinColumn(name="id", referencedColumnName="id", nullable=true)
      */
     private $userDetail;

     ...
}

and here is the UserDetail with its ID's @GeneratedValue removed

/**
 * @ORM\Table(name="user_detail", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
 * @ORM\Entity
 */
class UserDetail extends Entity
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     */
    private $id;

    ...
}

At this point what my expectation was to be able to do something like:

$user = new User();
$userDetail = new UserDetail();

$user->setUserDetail($userDetail)

$entityManager->persist($user);
$entityManager->flush();

And get two records persisted to the user and user_detail tables with identical IDs, but the reality is, not having any strategy defined for the UserDetail's identifier, doctrine will complaint about the missing ID, Entity of type UserDetail is missing an assigned ID for field 'id'.

Of course it is possible to do the job manually and in more than one call

$user = new User();
$entityManager->persist($user);
$entityManager->flush();

$userDetail = new UserDetail();
$userDetail->setId($user->getId)    
$user->setUserDetail($userDetail)

$entityManager->persist($user);
$entityManager->flush();

But I'm still hoping there is a correct configuration (annotation) that can help me to avoid such extra steps and leave handling of a one-to-one relationship through the entity's IDs to Doctrine.

like image 378
Ali Avatar asked Sep 07 '25 07:09

Ali


1 Answers

This is untested but I think the following might work, according to the docs (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html):

    /**
     * @ORM\Table(name="user_detail", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
     * @ORM\Entity
     */
    class UserDetail extends Entity
    {
        /**
         * @var integer
         *
         * @ORM\OneToOne(targetEntity="User")
         * @ORM\JoinColumn(name="id", referencedColumnName="id")
         * @ORM\Id
         */
        private $user;

    ...
    }
like image 122
Will Avatar answered Sep 09 '25 03:09

Will