tho*_*rad 2 query-builder symfony doctrine-orm
我正在尝试使用 Doctrine 的 Query Builder 创建一个非常复杂的查询(我使用的是 Doctrine 2.2)。在模型中,我有一个Distributor类和一个DistributorVisit具有一对多关系的类。每次代表访问分销商时,都会在DistributorVisit表中添加一个包含访问日期的新行。可以在此处找到这两个表的 ER 图。
现在我希望能够通过他们的上次访问日期过滤经销商。因此,用户输入一个日期范围(上次访问日期和上次访问日期),并列出上次访问日期介于这两个日期之间的经销商。我正在使用 Doctrine 的查询生成器,因为我在过滤器中执行了许多其他条件查询,而且我发现面向对象的方法在这种情况下效果最好。这是我在DistributorRepository课堂上所做的:
$qb = $this->getEntityManager()->createQueryBuilder()
->select('o')
->from('MyBundle:Distributor', 'o');
// Lots of 'andWhere's here
$qbv = $this->getEntityManager()->createQueryBuilder();
$qb->andWhere($qb->expr()->between(
$qbv->select($qbv->expr()->max('v.visitDate'))
->from('MyBundle:DistributorVisit', 'v')
->join('MyBundle:Distributor', 'o2',
Join::WITH,
$qbv->expr()->andX(
$qbv->expr()->eq('o2.id', 'v.distributorId'),
$qbv->expr()->eq('o2.id', 'o.id')
))
->getDQL(),
$filter->getLastVisitFrom()->getTimestamp(),
$filter->getLastVisitTo()->getTimestamp()
));
Run Code Online (Sandbox Code Playgroud)
这给了我以下错误:
[Syntax Error] line 0, col 83: Error: Expected Literal, got 'SELECT'
Run Code Online (Sandbox Code Playgroud)
我想这是因为查询生成器期望我的子选择所在的文字,但是,子查询的结果应该是文字,对吗?可能是因为查询生成器没有相应地添加括号?
非常感谢你的帮助。
我现在通过以下方式解决了这个问题:
$qb = $this->getEntityManager()->createQueryBuilder()
->select('o')
->from('MyBundle:Distributor', 'o');
$qbdv = $this->getEntityManager()->createQueryBuilder();
$qbdv->select('MAX(dv2.visitDate)')
->from('MyBundle:DistributorVisit', 'dv2')
->where($qbdv->expr()->eq('dv2.distributor', 'o'));
$maxVisitDate = '('.$qbdv->getDQL().')';
$qb->leftJoin(
'o.distributorVisits',
'dv',
Join::WITH,
$qb->expr()->eq('dv.visitDate', $maxVisitDate)
);
$qb->andWhere(
$qb->expr()->between(
'dv.visitDate',
':dateFrom',
':dateTo'
)
)
->setParameter('dateFrom', $filter->getLastVisitFrom())
->setParameter('dateTo', $filter->getLastVisitTo());
Run Code Online (Sandbox Code Playgroud)
所以我基本上做了以下事情:我将DistributorVisit表加入到Distributor具有最大访问日期的表中。诀窍在于,可以将(子)查询 ( $qb1->getDQL())的 DQL直接传递给 Doctrine 表达式 ( $qb2->expr()->eq('column', $qb1->getDQL())。我在上面的代码中使用左连接做到了这一点。
| 归档时间: |
|
| 查看次数: |
13494 次 |
| 最近记录: |