学说实体协会不工作

时间:2017-03-06 17:11:42

标签: php doctrine-orm symfony

我有两个配置为User和ApiKey的实体。他们在下面有一对一的关系映射。

用户:

/**
 * @var integer
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @ORM\Column(name="username", type="string", length=225, unique=true)
 * @Assert\NotBlank(message="Please enter a username.")
 * @Assert\Length(
 *     min = 2,
 *     max = 180,
 *     minMessage = "Your username must be at least {{ limit }} characters",
 *     maxMessage = "Your username cannot be longer than {{ limit }} characters"
 * )
 */
protected $username;

/**
 * @ORM\Column(name="email", type="string", length=225)
 * @Assert\NotBlank(message="Please enter a email.")
 * @Assert\Email(message = "The email '{{ value }}' is not a valid email.")
 */
protected $email;

/**
 * @ORM\Column(name="salt", type="text")
 */
protected $salt;

/**
 * @ORM\Column(name="password", type="string", length=225)
 * @Assert\NotBlank(message="Please enter a password.")
 * @Assert\Length(
 *     min = 7,
 *     minMessage = "Your password must be at least {{ limit }} characters long."
 * )
 */
protected $password;

/**
 * @Assert\NotBlank(message="Please enter a confirmation password.")
 */
protected $confirmationPassword;

/**
 * @ORM\Column(name="roles", type="json_array")
 */
protected $roles;

/**
 * @ORM\OneToOne(targetEntity="ApiKey", mappedBy="user")
 * @ORM\JoinColumn(name="id", referencedColumnName="user_id")
 */
protected $apiKey;

ApiKey:

/**
 * @var integer
 * @ORM\Column(name="user_id", type="integer")
 * @ORM\Id
 */
protected $user_id;

/**
 * @var string
 * @ORM\Column(name="api_key", unique=true, type="string", length=225)
 * @Assert\NotBlank(message="Please enter a username.")
 */
protected $api_key;

/**
 * @var string
 * @ORM\Column(name="expires", type="datetime")
 * @Assert\NotBlank(message="Please enter a username.")
 */
protected $expires;

/**
 * @ORM\OneToOne(targetEntity="User", inversedBy="apiKey")
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 */
protected $user;

但是,当我运行以下代码时:

$user = new User();
    $user->setUsername($request->get('username'));
    $user->setSalt(uniqid(mt_rand(), true));
    $user->setPassword(hash('sha256', $user->getSalt() . $request->get('password')));
    $user->setRoles(['ROLE_API']);

    $apiKey = new ApiKey();
    $apiKey->setUser($user);

    $this->getDoctrine()->getManager()->persist($user);
    $this->getDoctrine()->getManager()->flush();

我收到这个错误,我做错了什么?

  

执行' INSERT INTO用户(用户名,电子邮件,盐,密码,角色,ID)VALUES(?,?,?,?,?,?)'使用参数[" bobsmith"," bob@live.com" ;," 147423531058bd98d9ac9af4.48409486"," 6196012972b1294e7f3fbf9c140bc26f0bf3b354ea37d00753bc1ecba0a72866"," [ \" ROLE_API \"]",null]:SQLSTATE [23000]:完整性约束违规:1452无法添加或更新子行:外键约束失败(appusers,CONSTRAINT FK_1483A5E9BF396750外键(id)参考api_keyuser_id))

变化:

    $user = new User();
    $user->setUsername($request->get('username'));
    $user->setSalt(uniqid(mt_rand(), true));
    $user->setPassword(hash('sha256', $user->getSalt() . $request->get('password')));
    $user->setRoles(['ROLE_API']);

    $apiKey = new ApiKey();
    $this->getDoctrine()->getManager()->persist($apiKey); 
    $apiKey->setUser($user);

    $this->getDoctrine()->getManager()->persist($user);
    $this->getDoctrine()->getManager()->flush();
  

AppBundle \ Entity \ ApiKey类型的实体缺少字段' user_id'的已分配ID。此实体的标识符生成策略要求在调用EntityManager#persist()之前填充ID字段。如果您想要自动生成标识符,则需要相应地调整元数据映射。

2 个答案:

答案 0 :(得分:3)

这里似乎有一个级联问题。您正在将数据库中的用户保存,但该用户已链接到尚未保存在数据库中的ApiKey。要告诉玩家它需要保持它的ApiKey以及它需要在User和ApiKey之间保持持续级联

/**
 * @ORM\OneToOne(targetEntity="ApiKey", mappedBy="user", cascade="persist")
 */
protected $api_key;

如果您还想与用户一起删除ApiKey,您可以使用cascade={"persist", "remove"} 您可以找到有关关联here

的所有Doctrine文档

编辑:删除了所有者方面不存在的行// @ORM\JoinColumn(name="id", referencedColumnName="user_id"),如Chausser所评论

答案 1 :(得分:2)

这是2倍,Cyril说,但也因为你的用户类中有额外的映射:

/**
 * @ORM\OneToOne(targetEntity="ApiKey", mappedBy="user")
 * @ORM\JoinColumn(name="id", referencedColumnName="user_id") // Remove this line
 */
protected $apiKey;

应该是:

/**
 * @ORM\OneToOne(targetEntity="ApiKey", mappedBy="user")
 */
protected $apiKey;

只有实际执行映射的映射才需要连接列。通过使用mappedBy="user",您将告诉学说查看ApiKey类user属性以了解如何映射此关联。在此类中包含连接列会导致问题。