Reece Fowell
Reece Fowell

Reputation: 113

Cascading simple derived identity in Doctrine

How can I cascade a joined model with a OneToOne relationship where by only the User table has an auto increment strategy and the joined Profile model must have an id that matches the User id.

My models look like this:

Company\Model\User:

class User
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="integer")
     * @var int
     */
    private $id;

    /**
     * @OneToOne(targetEntity="Profile", inversedBy="user", cascade={"persist"})
     * @var Profile
     */
    private $profile;

Company\Model\Profile:

class Profile
{
    /**
     * @Id
     * @OneToOne(targetEntity="User", mappedBy="profile")
     * @JoinColumn(name="id")
     * @var User
     */
    private $user;

When persisting an instance of the User model, it causes the following error to be output:

Entity of type Company\Model\Profile is missing an assigned ID for field 'profile'. The identifier generation strategy for this entity requires the ID field to be populated before EntityManager#persist() is called. If you want automatically generated identifiers instead you need to adjust the metadata mapping accordingly.

The doctrine documentation calls this a simple derived identity, but does not explain how to cascade it.

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/composite-primary-keys.html#use-case-2-simple-derived-identity

Upvotes: 1

Views: 356

Answers (1)

Reece Fowell
Reece Fowell

Reputation: 113

It turns out that the answer is actually quite simple.

First the mappedBy and inversedBy need to be swapped around.

Secondly, when setting the Profile on the User you must set the user on the profile in turn.

Company\Model\User:

class User
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="integer")
     * @var int
     */
    private $id;

    /**
     * @OneToOne(targetEntity="Profile", mappedBy="user", cascade={"persist"})
     * @var Profile
     */
    private $profile;

    public function setProfile(Profile $profile): void
    {
        $this->profile = $profile;
        $this->profile->setUser($this);
    }

Company\Model\Profile:

class Profile
{
    /**
     * @Id
     * @OneToOne(targetEntity="User", inversedBy="profile")
     * @JoinColumn(name="id")
     * @var User
     */
    private $user;

Upvotes: 4

Related Questions