实体内部的查询生成器 - 教义

Query Builder inside entity - Doctrine

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

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

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

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

不能在实体内部使用QueryBuilder,但您可以使用原则Criteria过滤集合(在SQL级别).检查 documentation chapter 8.8. Filtering Collections for more details on Criteria

If the collection has not been loaded from the database yet, the filtering API can work on the SQL level to make optimized access to large collections.

例如只获取活动订阅:

$subscriptions = $this->getCompanySubscriptions();

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

$subscriptions = $subscriptions ->matching($criteria);

这样你就可以解决你的性能问题,因为集合是直接使用 Criteria 中的条件从数据库加载的。

您遇到的问题可能是您需要在 Plan 加入,但 joining is not possible in a Criteria。因此,如果确实需要加入,那么您应该考虑使用自定义查询,您可以在其中根据公司的条件进行加入 EntityRepository(例如使用 QueryBuilder)。

注. 您问题中的 foreach 可以使用 the filter method from the ArrayCollection class 重写。过滤器接受一个谓词,所有满足该谓词的元素都将被返回。 另请参阅 here in the doctrine 2 class documentation 了解更多信息。

你的谓词看起来像:

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

然后:

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