原则插入-一对一关系而未获得reference_id

时间:2018-08-17 00:56:59

标签: php doctrine-orm doctrine zend-framework3

我有两个名为user和user_authentication的实体。它们定义了单向关系。关系类型是一对一的。意味着用户实体与用户认证实体具有一对一的关系。

理论实体显示在下面

/**
 * 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;


}

AND

/**
 * 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和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();

2 个答案:

答案 0 :(得分:1)

您当前正在做的是以一种类似于bi-directional OneToOne的方式建立uni-directional关系,但两者都不是。

User对象上的“ owner”属性是对Authentication对象的引用的唯一属性。通过设置User将其保留在数据库中,可以通过这种方式进行定义。

您还希望同时创建两个记录。这样,zen's asnwer是正确的:您必须允许它级联保留。我假设您还想在删除用户的情况下删除身份验证,因此您还必须级联持久化。 (毕竟这是一个OneToOne)。

因此,然后对其进行设置,您将在用户端使用它:

/**
 * @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选项中添加了“删除”
  • 更改了inversedBy中的属性映射,请引用属性而不是列! (与认证端相同)
  • $authentication属性上添加了身份验证类型(这在IDE中有效,例如PhpStorm)
  • $userId属性更改为双向关系的另一端
  • $userId更改为$user,因为它将容纳一个User对象
  • 设置返回目标映射而不是列映射

在上面,我已经使它起作用了,但是您应该反过来。仅仅因为:用户可以不通过身份验证而存在,但是身份验证在没有用户的情况下就不存在。

这样,更好的关系设置将是:

// 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;

这也显示在链接的双向文档中。下面的示例:

/** @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;

    // ...
}

答案 1 :(得分:0)

如果您使用的是单向关系,那么在User模型中,您需要设置

/**
 * @ORM\OneToOne(targetEntity="\User\Entity\UsersAuthentication", cascade={"persist"})
 */
protected $authentication;

您需要删除userId实体中的UsersAuthentication属性。