Doctrine Insert - 没有得到的一对一关系 reference_id
Doctrine Insert - one to one relation without getting reference_id
我有两个名为 user 和 user_authentication 的实体。它们定义了单向关系。关系类型是一对一的。意味着,用户实体与用户认证实体具有一对一的关系。
Doctrine 实体如下所示
/**
* User
*
* @ORM\Table(name="user")
* @ORM\Entity
*/
class User {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="first_name", type="string", length=40, nullable=false)
*/
private $firstName;
/**
* @var string
*
* @ORM\Column(name="last_name", type="string", length=40, nullable=true)
*/
private $lastName;
/**
* @var string
*
* @ORM\Column(name="gender", type="string", nullable=false)
*/
private $gender;
/**
* @var string
*
* @ORM\Column(name="availability", type="string", nullable=false)
*/
private $availability;
/**
* @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", mappedBy="User", cascade={"persist"})
* @ORM\JoinColumn(name="id", referencedColumnName="user_id")
*/
protected $authentication;
}
和
/**
* UsersAuthentication
*
* @ORM\Table(name="users_authentication")
* @ORM\Entity
*/
class UsersAuthentication {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var integer
*
* @ORM\Column(name="user_id", type="integer", nullable=false)
*/
private $userId;
/**
* @var string
*
* @ORM\Column(name="email", type="string", length=255, nullable=false)
*/
private $email;
/**
* @var integer
*
* @ORM\Column(name="phone", type="integer", nullable=false)
*/
private $phone;
/**
* @var string
*
* @ORM\Column(name="password", type="string", length=64, nullable=false)
*/
private $password;
/**
* @var string
*
* @ORM\Column(name="token", type="string", length=128, nullable=false)
*/
private $token;
/**
* @var string
*
* @ORM\Column(name="type", type="string", nullable=false)
*/
private $type;
/**
* @var \DateTime
*
* @ORM\Column(name="last_login", type="datetime", nullable=true)
*/
private $lastLogin;
}
我想一次性插入用户和user_authentication中的数据。例如,如以下代码中所述,但它不起作用。
// Create new User entity.
$user = new User();
(isset($data->firstName))?$user->setFirstName($data->firstName):'';
(isset($data->lastName))?$user->setLastName($data->lastName):'';
(isset($data->gender))?$user->setGender($data->gender):'';
(isset($data->availability))?$user->setAvailability($data->availability):'';
$userAuthEntity = new UsersAuthentication();
$userAuthEntity->setLastLogin($date);
(isset($data->email))?$userAuthEntity->setEmail($data->email):'';
(isset($data->password))?$userAuthEntity->setPassword($data->password):'';
(isset($data->phone))?$userAuthEntity->setPhone($data->phone):'';
(isset($data->type))?$userAuthEntity->setType($data->type):'';
$user->addAuthentication($userAuthEntity);
$this->entityManager->persist($user);
$this->entityManager->flush();
它给我以下错误:
SQLSTATE[23000]:违反完整性约束:1048 列 'user_id' 不能为空
我想做的有可能吗?
============================================= ======
阅读@rKeet 和@zen 的回答后,我按照@rKeet 的建议添加了双向映射,并将我的 addUser 代码更新为以下代码,它成功了。荣誉。
$user = new User();
$user->setFirstName($data->firstName) : '';
$user->setLastName($data->lastName) : '';
$user->setGender($data->gender) : '';
$user->setAvailability($data->availability) : '';
$UA = new UsersAuthentication();
$UA->setActive(1);
$UA->setCreatedDate($date);
$UA->setEmail($data->email);
$UA->setModifiedDate($date);
$UA->setPassword($this->authManager->generate_hash($data->password));
$UA->setPhone($data->phone);
$UA->setType($data->type);
$UA->setUser($user);
$user->setAuthentication($UA);
$this->entityManager->persist($user);
$this->entityManager->flush();
如果你使用的是单向关系,那么在User
模型中,你需要设置
/**
* @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", cascade={"persist"})
*/
protected $authentication;
并且您需要删除 UsersAuthentication
实体中的 userId
属性。
您目前正在做的是设置 bi-directional OneToOne relation in a way that looks like uni-directional 但两者都不是。
User
对象上的 "owner" 属性 是对 Authentication
对象的引用。您已经通过设置 User
保存数据库中的列来以这种方式定义它。
您还想同时创建两条记录。因此, 是正确的:您必须允许它持续级联。我假设您还想在用户被删除的情况下删除身份验证,因此您还必须级联持久。 (毕竟是一对一)
因此,然后在用户端进行设置:
/**
* @var Authentcation
*
* @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", inversedBy="user", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="id", referencedColumnName="user_id")
*/
protected $authentication;
在身份验证方面,您将拥有:
/**
* @var User
*
* @ORM\OneToOne(targetEntity="\User\Entity\User", mappedBy="authentication", nullable=false)
*/
protected $user;
通知:
- 所有者方有
inversedBy
而不是 mappedBy
(父/子类的东西 - 重要!Read up here)
- 在
cascade
选项中添加了 "remove"
- 更改了
inversedBy
中的 属性 映射,引用 属性,而不是列! (在身份验证方面相同)
- 在
$authentication
属性 上添加了身份验证类型(这适用于 IDE,例如 PhpStorm)
- 将
$userId
属性更改为双向关系的另一方
- 已将
$userId
更改为 $user
,因为它将包含一个 User
对象
- 设置return目标映射而不是列映射
上面我已经做到了,但是你应该有相反的关系。仅仅是因为:用户可以没有身份验证而存在,但身份验证不能没有用户。
因此,更好的关系设置是:
// User class
/**
* @var Authentication
*
* @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", mappedBy="user", cascade={"persist", "remove"})
*/
protected $authentication;
// Authentication class
/**
* @var User
*
* @ORM\OneToOne(targetEntity="\User\Entity\User", inversedBy="authentication", nullable=false)
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
这也显示在 Doctrine 的链接双向文档中。下面的例子:
/** @Entity */
class Customer
{
// ...
/**
* One Customer has One Cart.
* @OneToOne(targetEntity="Cart", mappedBy="customer")
*/
private $cart;
// ...
}
/** @Entity */
class Cart
{
// ...
/**
* One Cart has One Customer.
* @OneToOne(targetEntity="Customer", inversedBy="cart")
* @JoinColumn(name="customer_id", referencedColumnName="id")
*/
private $customer;
// ...
}
我有两个名为 user 和 user_authentication 的实体。它们定义了单向关系。关系类型是一对一的。意味着,用户实体与用户认证实体具有一对一的关系。
Doctrine 实体如下所示
/**
* User
*
* @ORM\Table(name="user")
* @ORM\Entity
*/
class User {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="first_name", type="string", length=40, nullable=false)
*/
private $firstName;
/**
* @var string
*
* @ORM\Column(name="last_name", type="string", length=40, nullable=true)
*/
private $lastName;
/**
* @var string
*
* @ORM\Column(name="gender", type="string", nullable=false)
*/
private $gender;
/**
* @var string
*
* @ORM\Column(name="availability", type="string", nullable=false)
*/
private $availability;
/**
* @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", mappedBy="User", cascade={"persist"})
* @ORM\JoinColumn(name="id", referencedColumnName="user_id")
*/
protected $authentication;
}
和
/**
* UsersAuthentication
*
* @ORM\Table(name="users_authentication")
* @ORM\Entity
*/
class UsersAuthentication {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var integer
*
* @ORM\Column(name="user_id", type="integer", nullable=false)
*/
private $userId;
/**
* @var string
*
* @ORM\Column(name="email", type="string", length=255, nullable=false)
*/
private $email;
/**
* @var integer
*
* @ORM\Column(name="phone", type="integer", nullable=false)
*/
private $phone;
/**
* @var string
*
* @ORM\Column(name="password", type="string", length=64, nullable=false)
*/
private $password;
/**
* @var string
*
* @ORM\Column(name="token", type="string", length=128, nullable=false)
*/
private $token;
/**
* @var string
*
* @ORM\Column(name="type", type="string", nullable=false)
*/
private $type;
/**
* @var \DateTime
*
* @ORM\Column(name="last_login", type="datetime", nullable=true)
*/
private $lastLogin;
}
我想一次性插入用户和user_authentication中的数据。例如,如以下代码中所述,但它不起作用。
// Create new User entity.
$user = new User();
(isset($data->firstName))?$user->setFirstName($data->firstName):'';
(isset($data->lastName))?$user->setLastName($data->lastName):'';
(isset($data->gender))?$user->setGender($data->gender):'';
(isset($data->availability))?$user->setAvailability($data->availability):'';
$userAuthEntity = new UsersAuthentication();
$userAuthEntity->setLastLogin($date);
(isset($data->email))?$userAuthEntity->setEmail($data->email):'';
(isset($data->password))?$userAuthEntity->setPassword($data->password):'';
(isset($data->phone))?$userAuthEntity->setPhone($data->phone):'';
(isset($data->type))?$userAuthEntity->setType($data->type):'';
$user->addAuthentication($userAuthEntity);
$this->entityManager->persist($user);
$this->entityManager->flush();
它给我以下错误: SQLSTATE[23000]:违反完整性约束:1048 列 'user_id' 不能为空
我想做的有可能吗?
============================================= ======
阅读@rKeet 和@zen 的回答后,我按照@rKeet 的建议添加了双向映射,并将我的 addUser 代码更新为以下代码,它成功了。荣誉。
$user = new User();
$user->setFirstName($data->firstName) : '';
$user->setLastName($data->lastName) : '';
$user->setGender($data->gender) : '';
$user->setAvailability($data->availability) : '';
$UA = new UsersAuthentication();
$UA->setActive(1);
$UA->setCreatedDate($date);
$UA->setEmail($data->email);
$UA->setModifiedDate($date);
$UA->setPassword($this->authManager->generate_hash($data->password));
$UA->setPhone($data->phone);
$UA->setType($data->type);
$UA->setUser($user);
$user->setAuthentication($UA);
$this->entityManager->persist($user);
$this->entityManager->flush();
如果你使用的是单向关系,那么在User
模型中,你需要设置
/**
* @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", cascade={"persist"})
*/
protected $authentication;
并且您需要删除 UsersAuthentication
实体中的 userId
属性。
您目前正在做的是设置 bi-directional OneToOne relation in a way that looks like uni-directional 但两者都不是。
User
对象上的 "owner" 属性 是对 Authentication
对象的引用。您已经通过设置 User
保存数据库中的列来以这种方式定义它。
您还想同时创建两条记录。因此,
因此,然后在用户端进行设置:
/**
* @var Authentcation
*
* @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", inversedBy="user", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="id", referencedColumnName="user_id")
*/
protected $authentication;
在身份验证方面,您将拥有:
/**
* @var User
*
* @ORM\OneToOne(targetEntity="\User\Entity\User", mappedBy="authentication", nullable=false)
*/
protected $user;
通知:
- 所有者方有
inversedBy
而不是mappedBy
(父/子类的东西 - 重要!Read up here) - 在
cascade
选项中添加了 "remove" - 更改了
inversedBy
中的 属性 映射,引用 属性,而不是列! (在身份验证方面相同) - 在
$authentication
属性 上添加了身份验证类型(这适用于 IDE,例如 PhpStorm) - 将
$userId
属性更改为双向关系的另一方 - 已将
$userId
更改为$user
,因为它将包含一个User
对象 - 设置return目标映射而不是列映射
上面我已经做到了,但是你应该有相反的关系。仅仅是因为:用户可以没有身份验证而存在,但身份验证不能没有用户。
因此,更好的关系设置是:
// User class
/**
* @var Authentication
*
* @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", mappedBy="user", cascade={"persist", "remove"})
*/
protected $authentication;
// Authentication class
/**
* @var User
*
* @ORM\OneToOne(targetEntity="\User\Entity\User", inversedBy="authentication", nullable=false)
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
这也显示在 Doctrine 的链接双向文档中。下面的例子:
/** @Entity */
class Customer
{
// ...
/**
* One Customer has One Cart.
* @OneToOne(targetEntity="Cart", mappedBy="customer")
*/
private $cart;
// ...
}
/** @Entity */
class Cart
{
// ...
/**
* One Cart has One Customer.
* @OneToOne(targetEntity="Customer", inversedBy="cart")
* @JoinColumn(name="customer_id", referencedColumnName="id")
*/
private $customer;
// ...
}