Symfony 2:过滤x-to-many关系

时间:2012-08-03 10:45:59

标签: symfony doctrine

我有两个代表用户(User)和友情请求(FriendshipRequest)的实体。 User和FriendshipRequest之间存在oneToMany关系,因此Doctrine在类User中创建一个名为getFriendshipRequests()的方法。这没关系,但是FriendshipRequest有一个名为status的属性,所以我希望User类可以过滤与其关联的友情请求,以及其状态。我已经阅读了Doctrine文档,我发现了这个:

  

本地,您无法过滤2.0和2.1中的关联。你应该用   DQL查询以查询已过滤的实体集。

根据这个,我想我应该创建一个FriendshipRequest存储库并创建一个名为“findByStatusAndUser”的方法(或类似的东西),但我认为这是一个糟糕的解决方案。

我想在User实体中有一个方法,比如getPendingStatusRequests()。这可能吗?如果不是,最好的解决方案是什么?

3 个答案:

答案 0 :(得分:2)

从Doctrine 2.3开始,您可以使用matching and Criteria 然后,您可以在用户实体中使用getPendingStatusRequests(),就像您想要的那样。 对于您的示例,代码如下所示:

public function getPendingStatusRequests()
{
    $criteria = Criteria::create(); //don't forget to use Doctrine\Common\Collections\Criteria;
    $criteria->where(Criteria::expr()->eq('status', 1));

    return $this->friendshipRequests->matching($criteria);
}

答案 1 :(得分:1)

我认为FriendshipRequest存储库中的“getPendingRequestsForUser($ user)”方法应该是一个很好的解决方案。在这个方法中你只需要创建一个合适的DQL。

这是一个很好的解决方案,因为所有逻辑都应该移动到存储库,使实体尽可能小而干净。

UPD:另外,您可以使用findBy方法,如前所述here,例如:

$pendingRequests = $em->getRepository('MyBundle:FriendshipRequest')->findBy(
    array('user' => $user->getId(), 'status' => 1)
);

但对我来说,首选方法是首选。

答案 2 :(得分:0)

您当然可以将getPendingStatusRequests()添加到用户,然后让它循环遍历所有友谊请求,并仅返回具有相应状态的请求。

唯一的潜在问题是所有的友情请求都将被加载,包括那些你不需要的。由您来决定这是否是一个真正的问题。可能是一旦处理了友谊请求,它就会被删除,因此用户在任何给定时间都不会有很多请求。

如果您确实希望避免加载所有请求,请进行查询并在join子句中使用WITH表达式。类似的东西:

$qb->leftJoin('user.friendshipRequests','request', 
        Expr\Join::WITH, $qb->expr()->eq('request.status', $qb->expr()->literal('Pending')));

由于您使用的是S2,我不会愚弄存储库。只需创建一个名为UserManager的服务,注入实体管理器,并为其提供一个名为loadUserWithPendingFriendshipRequests的方法。