实体内部的查询生成器-条令


Query Builder inside entity - Doctrine

我正在寻找一种更好的方法来编写这个函数。它在一个条令实体模型中

public function getCompanySubscriptions()
{
    foreach ($this->subscriptions as $key => $value) {
        if ($value->getPlan()->getType() == 'E' && $value->getActive()) {
            return $value;
        }
    }
    return null;
}

$this->subscriptions是一个多对一集合,可以有不同的"类型"(但其中只有一个类型为"E")。

问题是:如果Company有太多的$subscriptions,这个函数将太慢,无法返回类型为"E"的唯一一个,我在使用TWIG构建视图时需要检查它。解决方案是使用QueryBuilder,但我还没有找到直接从实体模型中使用它的方法。

不能在实体内部使用QueryBuilder,而是可以使用原则Criteria来过滤集合(在SQL级别上)。查看文档章节8.8。筛选集合以获取有关Criteria的更多详细信息。

如果尚未从数据库加载集合,则筛选API可以在SQL级别工作,以优化对大型集合的访问。

例如,只获取活动订阅:

$subscriptions = $this->getCompanySubscriptions();
$criteria = Criteria::create()
    ->where(Criteria::expr()->eq("active", true));
$subscriptions = $subscriptions ->matching($criteria);

与此类似,您可以解决性能问题,因为集合是直接使用Criteria中的条件从数据库加载的。

在您的情况下,问题可能是您需要在Plan上加入,但在Criteria中不可能加入。因此,如果连接确实是必要的,那么您应该考虑使用自定义查询,在该查询中,您使用公司EntityRepository中的条件进行连接(例如,使用QueryBuilder)。

注意问题中的foreach可以使用ArrayCollection类的filter方法重写。过滤器接受一个谓词,所有满足该谓词的元素都将被返回。更多信息,请参阅条令2类文档中的此处。

你的谓词看起来像:

$predicate = function($subscription){
    $subscription->getPlan()->getType() == 'E' && $subscription->getActive();
}

然后:

return $this->subscriptions->filter($predicate);