使用来自父实体的生成值

Using generatedvalue from parent entity

我在我们的项目中有两个使用 Doctrine 的实体:

class User
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $user_id;

    /**
     * @ORM\Column(type="string")
     */
    private $username;

    /**
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @ORM\OneToOne(targetEntity="UserProfile", cascade={"persist", "remove"})
     * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id", unique=true)
     * @var UserProfile
     */
    private $profile;

    //...
}

class UserProfile
{
    /**
     * @ORM\Id
     * @ORM\OneToOne(targetEntity="User")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
     */
    private $user;

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    private $user_id;

    /**
     * @ORM\Column(type="string")
     */
    private $first_name = '';

    /**
     * @ORM\Column(type="string")
     */
     private $last_name = '';

     //...
}

我正在尝试使用类似以下内容在数据库中生成新行:

$user = new User();
$user->setUsername('test');
$user->setEmail('test@example.com');
$user->setPassword(password_hash('password', PASSWORD_BCRYPT));

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

$userProfile = new UserProfile();
$userProfile->setFirstName('test');
$userProfile->setLastName('user');

$user->setProfile($userProfile);

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

这似乎与此处的示例类似: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/composite-primary-keys.html#use-case-2-simple-derived-identity

这会引发错误:

Fatal error: Uncaught Doctrine\ORM\ORMException: Entity of type App\Entity\UserProfile is missing an assigned ID for field 'user'. 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. in /home/site/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php on line 87

如果我添加一个没有 UserProfile 的用户,这可以正常工作,并且我在数据库中得到一行 user_id 是从 MySQL 自动增量生成的。创建新配置文件时如何让 UserProfile 使用新创建的 user_id?

我是不是把协会的事情复杂化了?我应该只在 UserProfile 上创建一个 setUserId() 方法吗?

UserUserProfile 实体之间的关系保留在 UserProfile::user 属性 上,但是,当您调用 User::setProfile() 时,您没有设置 属性.

将您的 User::setProfile() 函数更改为以下内容:

function setProfile(UserProfile $profile): self
{
    $profile->setUser($this);
    $this->profile = $profile;

    return $this;
}

您的映射无效。验证您的架构 - 缺少 mappedByinversedBy。当您修复映射时,这将按预期工作。

正在 Symfony 中验证架构:

bin/console doc:sch:val

采埃孚:

php public/index.php orm:schema-tool:validate

感谢@emix 和@fubar,他们都为解决方案做出了贡献。这就是最终起作用的:

class User
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $user_id;

    /**
     * @ORM\Column(type="string")
     */
    private $username;

    /**
     * @ORM\Column(type="string")
     */
    private $password;

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

    //...

    public function setProfile(UserProfile $profile) : self
    {
        $profile->setUser($this);

        $this->profile = $profile;

        return $this;
    }
}

class UserProfile
{
    /**
     * @ORM\Id
     * @ORM\OneToOne(targetEntity="User", inversedBy="profile")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
     */
    private $user;

    /**
     * @ORM\Column(type="string")
     */
    private $first_name = '';

    /**
     * @ORM\Column(type="string")
     */
     private $last_name = '';

     //...
}

其中涉及从 UserProfile 实体中删除 $user_id 并将 inversedBy 参数添加到 OneToOne。

User 实体中删除 JoinColumn 并修复 setProfile() 的 setter,以便在 UserProfile 实体上设置 $user