Php 优化条令查询以防止附加查询

Php 优化条令查询以防止附加查询,php,mysql,symfony,doctrine-orm,doctrine,Php,Mysql,Symfony,Doctrine Orm,Doctrine,我正在构建一个有更新墙的系统,在这里你只能看到朋友的帖子。 这里的“朋友”由两个用户组成,每个用户都将彼此添加到他们的朋友列表中 朋友关系的处理非常简单,只需一个条令manytomy关系,如下所示: User.php //.. other declarations /** * @var ArrayCollection * @ORM\ManyToMany(targetEntity="User") * @ORM\JoinTable(name="user_friends") */ protec

我正在构建一个有更新墙的系统,在这里你只能看到朋友的帖子。 这里的“朋友”由两个用户组成,每个用户都将彼此添加到他们的朋友列表中

朋友关系的处理非常简单,只需一个条令
manytomy
关系,如下所示:

User.php

//.. other declarations
/**
 * @var ArrayCollection
 * @ORM\ManyToMany(targetEntity="User")
 * @ORM\JoinTable(name="user_friends")
 */
protected $friends;
//.. more unrelated stuff
并在我的查询中获得用户朋友的更新(包括他们自己)

UpdateRepository.php

/**
 * Get aggregated list of updates for a user and their friends in chronological order
 * @param User $user
 * @return array
 */
public function getWallUpdates(User $user)
{
    $qb = $this->getEntityManager()->createQueryBuilder('p');
    $qb->select(['p'])->from($this->getEntityName(), 'p');

    $criteria = $qb->expr()->andX();

    // Filter based on Friends
    $friends = [$user];
    foreach($user->getFriends() as $friend) // collect eligible friends
        if($friend->getFriends()->contains($user))
            $friends[] = $friend;

    $criteria->add('p.account IN (:friends)');
    $qb->setParameter('friends', $friends);

    // Filter based on Chronology

    // Filter based on Privacy
    $criteria->add('p.privacy IN (:privacy)');
    $qb->setParameter('privacy', [1, 3]);

    $qb->where($criteria);

    $query = $qb->getQuery();
    $result = $query->getResult();

    return $result;
}
现在这个可以运行了,但问题是,
如果($friend->getFriends()->包含($user))
行需要知道另一个用户的朋友列表中是否存在
$user
,它会为
$user
的朋友列表中的每个人生成一个新的查询

我不介意用一两个额外的查询来完成这个任务,但我需要在这里讨论一下规模。此应用程序上的一个人可能有数百个朋友。我无法在每次加载此页面时执行数百个查询(尽管它们可能很小),这可能会非常多

让这一切变得更好的最佳解决方案是什么

现在我可以继续开发,因为它确实正常工作

编辑

为了简洁起见,我确实尝试过使用
EXTRA\u LAZY
方法,在我的用户实体中向$friends manytomy声明添加
EXTRA\u LAZY
。根据文档,如果使用
EXTRA_LAZY
fetch模式,使用
Collection#contains(entity)
不会触发查询

显然,这里的问题源于这样一个事实,
$user
s的朋友都需要收集他们的朋友列表以便进行检查。这对我来说很有意义


还有一种方法可以将这一切合并到一个操作中吗?

如果在获取$user对象时为用户的朋友和他们的朋友添加连接,那么它应该可以删除任何延迟加载。例如,您可以为用户创建一个自定义存储库,如下所示:

use Doctrine\ORM\EntityRepository;

class UserRepository extends EntityRepository {

    public function fetchFriendsOfFriends($userId) {
        return $this->_em->createQuery('SELECT u, f, ff FROM User u '
                . 'LEFT JOIN u.friends f '
                . 'LEFT JOIN f.friends ff '
                . 'WHERE u.id = :userId')
            ->setParameter('userId', $userId)
            ->getSingleResult();
    }
}
获取您的用户实体以使用此存储库:

/**
 * @ORM\Entity(repositoryClass="UserRepository")
 */
class User {
...
然后,在获取$user时,使用新的获取方法:

$user = $em->getRepository('User')->fetchFriendsOfFriends($userId);
我还没有对它进行测试,但我认为它会减少延迟加载的需要