Php 条令';这是多对多的自我参照和互惠

Php 条令';这是多对多的自我参照和互惠,php,doctrine-orm,doctrine,many-to-many,Php,Doctrine Orm,Doctrine,Many To Many,默认情况下,自参考原则下的许多关系都涉及拥有方和相反方,如中所述 有没有一种方法可以实现双方之间没有差别的互惠关系 以下是文档中的示例: <?php /** @Entity **/ class User { // ... /** * @ManyToMany(targetEntity="User") **/ private $friends; public function __construct() { $this-&

默认情况下,自参考原则下的许多关系都涉及拥有方和相反方,如中所述

有没有一种方法可以实现双方之间没有差别的互惠关系

以下是文档中的示例:

<?php
/** @Entity **/
class User
{
    // ...

    /**
     * @ManyToMany(targetEntity="User")
     **/
    private $friends;

    public function __construct() {
        $this->friends = new \Doctrine\Common\Collections\ArrayCollection();
    }

    // ...
}

解决这个问题的方法有很多,都取决于“朋友”关系的要求

单向的

一种简单的方法是使用单向多人关联,并将其视为双向关联(保持双方同步):

当您调用
$userA->addFriend($userB)
时,
$userB
将添加到
$userA
中的好友集合,而
$userA
将添加到
$userB
中的好友集合

它还将导致在“friends”表中添加2条记录(1,2和2,1)。虽然这可以看作是重复的数据,但它将大大简化您的代码。例如,当您需要查找
$userA
的所有好友时,您只需执行以下操作:

SELECT u FROM User u JOIN u.friends f WHERE f.id = :userId
无需像双向关联一样检查两个不同的属性

双向

使用双向关联时,
用户
实体将有两个属性,例如,
$myFriends
$friendsWithMe
。您可以使用与上述相同的方式使它们保持同步

主要区别在于,在数据库级别上,只有一条记录表示关系(1,2或2,1)。这使得“查找所有朋友”查询更为复杂,因为您必须同时检查这两个属性

当然,您仍然可以使用数据库中的2条记录,方法是确保
addFriend()
将同时更新
$myFriends
$friendsWithMe
(并保持另一端同步)。这将在实体中增加一些复杂性,但查询会变得不那么复杂

OneToMany/manytone

如果您需要一个系统,其中用户可以添加朋友,但该朋友必须确认他们确实是朋友,那么您需要将确认信息存储在join表中。然后,您不再有多个关联,而是像
用户
友谊
用户

您可以阅读我关于此主题的博客帖子:


单向=>无法确定属性的访问类型
您需要映射
id
属性。我已经将它添加到示例中(映射为整数,但它可以是您喜欢的任何东西)。非常有用的答案。对我来说,要添加的重要部分是
$user->addFriend($this)。克隆此实体时,它不采用双向链接。但是我必须添加“公共函数uu clone(){foreach($this->getFriends()as$thatFriend){$thatFriend->addFriend($this);}”
SELECT u FROM User u JOIN u.friends f WHERE f.id = :userId