【问题标题】:Doctrine 2.1 Identity through foreign Entities One-To-One Bidirectional Association学说 2.1 通过外国实体的身份一对一的双向关联
【发布时间】:2012-08-31 06:39:02
【问题描述】:

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

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

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

[PDO异常]

SQLSTATE[23000]:完整性约束违规:1452 无法添加或更新子行:外键约束失败(table.user,CONSTRAINT FK_187DDE86BF396750 FOREIGN KEY(id)参考address (user_id))

这是我的实体:

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

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

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

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

更新 1:

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

老实说,我不确定关系的反面是什么意思,因为“仅对关联反面所做的更改会被忽略”

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

有什么意义?

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

$user->setAddress($address);

而不是:

$address->setUser($user);

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

  1. 使关系双向刹车
  2. User 的一面必须是反面,所以 $user->setAddress($address); 无论如何都会被忽略!!

有人能解释一下吗:)

马修

【问题讨论】:

    标签: php doctrine-orm foreign-keys


    【解决方案1】:

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

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

    • 在您的“实体部分”:您的两个实体都有一个相互引用的属性。在您的情况下,您在用户中有 $address,在地址中有 $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 无法自动更新另一方。所以你必须手动完成。由于无需在每次创建新用户和地址时都考虑这一点,您可以在 setter 中自动执行该过程:

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

    【讨论】:

      【解决方案2】:

      您的用户实体中定义的地址字段是否有 getter?

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

      请记住,学说总是返回集合。

      【讨论】:

      • 感谢 Max,但这不是问题所在。是的,当我在 User 实体中添加 $address 字段时,会在 User 实体类中为我生成 getAddress() 方法。但是,对于 User 实体上的 $address 字段,FK 约束被添加到数据库中 user 表中的 id 列。这个 FK 约束阻止数据像 $address = new Address(); $address-&gt;setUser($user); 这样被加载到数据库中。
      • 我的另一个拍摄是这个用户有地址,而你正在尝试添加另一个。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-04
      • 1970-01-01
      相关资源
      最近更新 更多