通常,您可以随时使用单向或双向关系。您设计代码是因为您将使用它。也就是说,例如,如果您声明单向关系 oneToOne 是因为您只需要在一侧拥有信息。相反,如果您需要从两个实体访问有关另一个实体的信息,则需要声明您的双向关系。例如:
假设你的 User-Teacher 关系是 OneToOne。
案例 1:您需要知道用户是否是教师,并且您还需要知道哪个用户与教师实体相关 => 您使用双向关系。
/** @Entity */
class User
{
// ...
/**
* @OneToOne(targetEntity="Teacher", mappedBy="user")
*/
private $teacher;
// ...
}
/** @Entity */
class Teacher
{
// ...
/**
* @OneToOne(targetEntity="User", inversedBy="teacher")
* @JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
// ...
}
默认表看起来像:
CREATE TABLE Teacher (
id INT AUTO_INCREMENT NOT NULL,
user_id INT DEFAULT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE User (
id INT AUTO_INCREMENT NOT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE Teacher ADD FOREIGN KEY (user_id) REFERENCES User(id);
案例 2:您需要访问与教师相关的用户,但您永远不需要知道教师用户,因此您只声明了教师方面的一部分。
参考:
http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#one-to-one-unidirectional
有一些限制,主要是在 oneToMany 关系中。一般来说,我会建议你使用双向关系。
“Doctrine 文档在这里说,Doctrine 只会检查关联的拥有方是否有变化。这是什么意思?什么样的变化?”
我对此并不完全确定,但我可以告诉您我对此的理解:当您刷新实体中的更改时(在更改实体并执行 $entityManager->flush() 之后),它只会检查关系中主要实体的更改,也就是说,如果您在另一个实体中进行了更改,它将不会检查两个实体,而只会检查关系中的主要实体。因此,您必须将作为“基础”的那一方声明为所有者,而不是相反。例如,在前面的示例中,如果您从教师实体更改用户实体,Doctrine 不会考虑它,因为用户是所有者。
例如:
$teacher->getUser()->setName('john'); //Doctrine won't check for this change
$user->getTeacher()->setStatus('dismissed'); //Doctrine will track this change
正如我告诉你的那样,我没有测试过这种情况,因为我通常会很好地声明我的关系(你的 FK 将定义哪个是所有者方,在这种情况下是用户)。无论如何,进行测试并确认它并不难。