我可以在Doctrine的QueryBuilder中使用min()
(或等效的)吗?
我正在处理的页面显示了当前(或模拟)用户的发票表。它的每张发票都有一行,并且嵌套了任何关联付款的可折叠行(见下图)
我的问题是,在我的树枝模板中,如果任何付款尚未获得批准,我需要能够在发票级别进行识别。如果任何付款未获批准,那么我需要标记付款和与之相关的发票行。例如,在下面的示例中," Invoice#1"是黄色的,因为它有一个嵌套的#34;付款#2"记录为黄色(未批准):
要在发票级别访问此内容,我一直在尝试通过我的InvoiceRepository进行访问,但我不清楚是否/如何使用QueryBuilder完成此操作。我不知何故需要anyToBeApproved
(这不是我的发票实体的属性),并且还包含付款信息:
select a.*, min(b.approved) as anyToBeApproved
from Invoice a
left join Payment b
on a.invoice_id=b.id
where a.member_id=$Uid
group by a.id
$invoices = $em->getRepository('AppBundle:Invoice')->OutstandingForUser($this->getUser()->getId());
public function OutstandingForUser($Uid)
{
return $this->createQueryBuilder('i')
->select('i')
->leftJoin('i.member_id','m')
->leftJoin('i.payment_ids','p')
->andwhere('m.member_id = :MemberId' )
->setParameter('MemberId',$Uid)
->getQuery()
->getResult();
}
答案 0 :(得分:0)
我不知道为什么这还没有得到解答,但你应该可以正常使用这些聚合函数。
SELECT和GROUP BY中允许使用以下聚合函数 子句:AVG,COUNT,MIN,MAX,SUM
您可以在querybuilder中使用聚合函数 - > select()确定。
我将您的功能重写为:
public function OutstandingForUser($Uid)
{
return $this->createQueryBuilder('i')
->select('i, min(p.approved) as anyToBeApproved')
->leftJoin('i.member','m', 'WITH', 'm.member_id = :MemberId') // this works better with not actually constraining your left join, otherwise you might as well just use innerJoin
->leftJoin('i.payment','p')
->groupBy('i.id')
->setParameter('MemberId',$Uid)
->getQuery()
->getResult();
}
这是另一种方法,因为您似乎还想要所有发票行。
将您的获取功能更改为:
public function OutstandingForUser($Uid)
{
return $this->createQueryBuilder('i')
->select('i, p, m') // may as well pre-fetch all entities
->join('i.member','m') // member is surely mandatory? so no left join required
->leftJoin('i.payment','p') // payments may not be present, so left join
->where('m.member_id = :MemberId')
->setParameter('MemberId',$Uid)
->getQuery()
->getResult();
}
然后在您的发票实体中执行类似
的操作 public function hasUnapprovedPayments () {
foreach ($this->getPayments() as $payment) {
if (!$payment->approved()) {
return true;
}
}
return false;
}
public function hasPayments () {
return !$this->getPayments()->isEmpty(); // assuming doctrine collection
}
这些功能非常快,因为你已经在上面的函数中对实体进行了水合。
您还可以添加一个循环付款的类似isFullyPaid方法,但我个人会在发票完全支付时设置的发票上设置一个bool或datetime。
然后在树枝上你可以做类似的事情:
{% for invoice in invoices %}
{% if invoice.hasUnapprovedPayments %} do something {% endif %}
{% if invoice.hasPayments %} do something {% endif %}
{# loop through all your payments etc #}
{% endfor %}
这样可以很容易地获得所需的布局。