Php 条令插入-一对一关系,无需获取引用id

Php 条令插入-一对一关系,无需获取引用id,php,doctrine-orm,doctrine,zend-framework3,Php,Doctrine Orm,Doctrine,Zend Framework3,我有两个名为user和user\u authentication的实体。它们定义了单向关系。关系类型为一对一。也就是说,用户实体与用户认证实体之间存在一对一的关系 条令实体显示在下面 /** * User * * @ORM\Table(name="user") * @ORM\Entity */ class User { /** * @var integer * * @ORM\Column(name="id", type="integer", nullable=false) *

我有两个名为user和user\u 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;


}

我想一次性在用户和用户身份验证中插入数据。例如,如下面代码中所述,但它不起作用

    // 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列“用户id”不能为空

我想做的事有可能吗

===================================================

在阅读了@rKeet和@zen answers之后,我按照@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
属性。

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

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

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

您当前所做的是以一种看起来像但不是的方式设置关系

User
对象上的“owner”属性是对
Authentication
对象进行引用的属性。您通过设置
用户
在数据库中保存列来定义它

您还希望同时创建两个记录。这样做是正确的:您必须允许它持续存在。我假设您还希望在用户被删除的情况下删除身份验证,因此您还必须级联持久化。(毕竟这是一个单间)

因此,设置它时,用户端会有以下内容:

/**
 * @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
    (父/子类-很重要!)
  • 级联
    选项中添加了“删除”
  • 更改了
    inversedBy
    中的属性映射,请引用属性,而不是列!(身份验证侧相同)
  • $Authentication
    属性上添加了身份验证类型(这在诸如PhpStorm之类的IDE中有效)
  • $userId
    属性更改为双向关系的另一端
  • $userId
    更改为
    $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;

    // ...
}

你现在正在做的是建立一种关系,这种关系看起来像,但实际上不是

User
对象上的“owner”属性是对
Authentication
对象进行引用的属性。您通过设置
用户
在数据库中保存列来定义它

您还希望同时创建两个记录。这样做是正确的:您必须允许它持续存在。我假设您还希望在用户被删除的情况下删除身份验证,因此您还必须级联持久化。(毕竟这是一个单间)

因此,设置它时,用户端会有以下内容:

/**
 * @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
    (父/子类-很重要!)
  • 级联
    选项中添加了“删除”
  • 更改了
    inversedBy
    中的属性映射,请引用属性,而不是列!(身份验证侧相同)
  • $Authentication
    属性上添加了身份验证类型(这在诸如PhpStorm之类的IDE中有效)
  • $userId
    属性更改为双向关系的另一端
  • $userId
    更改为
    $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;

    // ...
}

成功了。谢谢。现在在我的问题中添加工作场景。如果我想在单个查询中同时更新用户和用户身份验证,该怎么办?我怎么能这么做?你不用问。让我来帮你处理。您只需通过EntityManager“获取”实体对象(例如,在controller
$this->getEntityManager()->getRepository(User::class)->find(2)
(获取id为2的用户))。然后对用户进行更改。然后调用
$this->getEntityManager()->persist($user)
,然后调用
$this->getEntityManager()->flush()
flush()
函数用于将所有要更新/创建、修改/删除的操作更新到数据库。再次感谢。我实际上是在问,如何同时对用户和用户身份验证进行更新。不过我得到了解决办法。看来你对zend和教义有很好的了解。我正在创造一种产品,可能会寻求您的指导。我可以付。如果可能,如果您通过EntityManager获取实体对象,您是否可以与meIf共享您的电子邮件id