原则2.1通过外国实体的身份一对一双向关联

时间:2012-08-31 06:39:02

标签: php doctrine-orm foreign-keys

我正在使用Doctrine 2.1,其中支持通过外国实体进行身份识别(外键作为标识符)。

http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/tutorials/composite-primary-keys.html#identity-through-foreign-entities

是否可以通过双向关系通过外国实体进行身份识别?我正在尝试但是当我加载数据夹具时出现以下错误:

  

[PDOException]

     

SQLSTATE [23000]:完整性约束违规:1452无法添加或更新子行:外键约束失败(tableuser,CONSTRAINT FK_187DDE86BF396750 FOREIGN KEY({{ 1}})参考idaddress))

以下是我的实体:

user_id

如果我从User删除引用,则错误消失!

我希望能够做到以下几点:

/**
 * @Entity
 */
class User
{
    /** @Id @Column(type="integer") @GeneratedValue */
    private $id;

    /** @OneToOne(targetEntity="Address") */
    private $address;
}

/**
 * @Entity
 */
class Address
{
    /** @Id @OneToOne(targetEntity="User") */
    private $user;
}

..但似乎我必须这样做:

$address = $user->getAddress();

是吗?有没有办法做到这一点?

更新1:

我希望能够从任何一方设置关系(双向),但这似乎不可能。

老实说,我不确定关系的反面是什么意思,因为“只会忽略关联的反面变化”

取自此处的文档:http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/association-mapping.html#owning-side-and-inverse-side

有什么意义?

从应用程序的角度来看,似乎更有意义:

$address = $entityManager->find('Address', $user->getId());

而不是:

$user->setAddress($address);

然而,第一个是不可能的,因为:

  1. 使关系双向制动事物
  2. $address->setUser($user);方必须是反面,所以User无论如何都会被忽略!!
  3. 请有人解释一下:)

    马修

2 个答案:

答案 0 :(得分:1)

您的问题与“外键作为标识符”无关,而是与关系的拥有方有关:

在Doctrine中,关系可能是双向的,但在这种情况下,关系必须具有“onwing-side”。这意味着:

    您的“实体部分”上的
  • :您的实体都具有相互引用的属性。在您的情况下,您在User中有$地址,在地址中有$ user,您可以使用$ user-> getAddress()和$ address-> getUser()

  • 在“sql部分”上:只有一个表(拥有方)具有引用另一个表的属性。

您可以通过在非拥有方使用“mappedBy”来通知Doctrin拥有哪一方。 在您的情况下,使用外键作为标识符,您无法选择:拥有方是具有外键的方。 所以,测试一下:

/**
 * @Entity
 */
class User
{
    /** @Id @Column(type="integer") @GeneratedValue */
    private $id;

    /** @OneToOne(targetEntity="Address", mappedBy="user") */
    private $address;
}

/**
 * @Entity
 */
class Address
{
    /** @Id @OneToOne(targetEntity="User", inversedBy="address")) */
    private $user;
}

另一个重点: 在双向关系中,当您设置非拥有方时,Doctrine无法自动更新另一方。所以你必须手工制作。为了在每次创建新用户和地址时都没有考虑到这一点,您可以在设置器中自动执行该过程:

// in class User :
public function setAddress($address) {
    $address->setUser($this);           // <= here it is !!!
    $this->address = $address;
    return $this;
}

// in class Address :
public function setUser($user) {
    $this->user = $user;
    return $this;
}

现在,您可以设置您想要的地址,而无需担心这些拥有的东西:

$address = new Addresse();
$address->set...
$user->setAddress($address);

答案 1 :(得分:0)

您是否拥有用户实体中定义的地址栏的吸气剂?

public function getAddress()
{
  return $this->address;
}

请记住,学说总是回归。