我正在寻找一种更好的方法来编写这个函数。它在一个条令实体模型中
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);