实体内部的查询生成器 - 教义
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);
我正在寻找一种更好的方法来编写此函数。 它在 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);