我正在使用Doctrine的QueryBuilder来构建查询,我想从查询中获得结果的总数。
$repository = $em->getRepository('FooBundle:Foo');
$qb = $repository->createQueryBuilder('n')
->where('n.bar = :bar')
->setParameter('bar', $bar);
$query = $qb->getQuery();
//this doesn't work
$totalrows = $query->getResult()->count();
我只想对此查询运行计数以获取总行数,但不返回实际结果。 (在此计数查询之后,我将使用maxResults进一步修改查询以进行分页。)
答案 0 :(得分:438)
类似的东西:
$qb = $entityManager->createQueryBuilder();
$qb->select('count(account.id)');
$qb->from('ZaysoCoreBundle:Account','account');
$count = $qb->getQuery()->getSingleScalarResult();
修改
有些人认为表达式比使用直接DQL更好。有人甚至编辑了一个四年前的答案。我把他的编辑推回去。 去图。
答案 1 :(得分:45)
以下是格式化查询的另一种方法:
return $repository->createQueryBuilder('u')
->select('count(u.id)')
->getQuery()
->getSingleScalarResult();
答案 2 :(得分:19)
将所有使用数据库的逻辑移到存储库中会更好。
所以在控制器中你写
/* you can also inject "FooRepository $repository" using autowire */
$repository = $this->getDoctrine()->getRepository(Foo::class);
$count = $repository->count();
并在Repository/FooRepository.php
public function count()
{
$qb = $repository->createQueryBuilder('t');
return $qb
->select('count(t.id)')
->getQuery()
->getSingleScalarResult();
}
最好将$qb = ...
移到单独的行,以防您想制作复杂的表达式,例如
public function count()
{
$qb = $repository->createQueryBuilder('t');
return $qb
->select('count(t.id)')
->where($qb->expr()->isNotNull('t.fieldName'))
->andWhere($qb->expr()->orX(
$qb->expr()->in('t.fieldName2', 0),
$qb->expr()->isNull('t.fieldName2')
))
->getQuery()
->getSingleScalarResult();
}
另请考虑缓存查询结果 - http://symfony.com/doc/current/reference/configuration/doctrine.html#caching-drivers
public function count()
{
$qb = $repository->createQueryBuilder('t');
return $qb
->select('count(t.id)')
->getQuery()
->useQueryCache(true)
->useResultCache(true, 3600)
->getSingleScalarResult();
}
在一些简单的情况下,使用EXTRA_LAZY
实体关系是好的
http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/tutorials/extra-lazy-associations.html
答案 3 :(得分:16)
如果您需要使用groupBy
,having
等来计算更复杂的查询...您可以借用Doctrine\ORM\Tools\Pagination\Paginator
:
$paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($query);
$totalRows = count($paginator);
答案 4 :(得分:5)
使用分组,联合和填充的示例。
问题:
$qb = $em->createQueryBuilder()
->select('m.id', 'rm.id')
->from('Model', 'm')
->join('m.relatedModels', 'rm')
->groupBy('m.id');
为此工作可能的解决方案是使用定制保湿剂和这个奇怪的事情 被称为“CUSTOM OUTPUT WALKER HINT”:
class CountHydrator extends AbstractHydrator
{
const NAME = 'count_hydrator';
const FIELD = 'count';
/**
* {@inheritDoc}
*/
protected function hydrateAllData()
{
return (int)$this->_stmt->fetchColumn(0);
}
}
class CountSqlWalker extends SqlWalker
{
/**
* {@inheritDoc}
*/
public function walkSelectStatement(AST\SelectStatement $AST)
{
return sprintf("SELECT COUNT(*) AS %s FROM (%s) AS t", CountHydrator::FIELD, parent::walkSelectStatement($AST));
}
}
$doctrineConfig->addCustomHydrationMode(CountHydrator::NAME, CountHydrator::class);
// $qb from example above
$countQuery = clone $qb->getQuery();
// Doctrine bug ? Doesn't make a deep copy... (as of "doctrine/orm": "2.4.6")
$countQuery->setParameters($this->getQuery()->getParameters());
// set custom 'hint' stuff
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, CountSqlWalker::class);
$count = $countQuery->getResult(CountHydrator::NAME);
答案 5 :(得分:5)
从Doctrine 2.6
开始,可以直接从count()
使用EntityRepository
方法。有关详细信息,请参阅链接。
答案 6 :(得分:4)
对于仅使用Doctrine DBAL而非Doctrine ORM的用户,他们将无法访问getQuery()
方法,因为它不存在。他们需要做类似以下的事情。
$qb = new QueryBuilder($conn);
$count = $qb->select("count(id)")->from($tableName)->execute()->fetchColumn(0);
答案 7 :(得分:4)
要计算一些项目(偏移量)之后的项目,$ qb-> setFirstResults()在这种情况下不能应用,因为它不作为查询条件,而是作为范围的查询结果的偏移量选择的项目(即setFirstResult不能用于收集COUNT)。因此,为了计算剩下的项目,我只需执行以下操作:
//in repository class:
$count = $qb->select('count(p.id)')
->from('Products', 'p')
->getQuery()
->getSingleScalarResult();
return $count;
//in controller class:
$count = $this->em->getRepository('RepositoryBundle')->...
return $count-$offset;
有人知道更干净的方式吗?
答案 8 :(得分:0)
将以下方法添加到存储库应该允许您从Controller中调用$repo->getCourseCount()
。
/**
* @return array
*/
public function getCourseCount()
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->select('count(course.id)')
->from('CRMPicco\Component\Course\Model\Course', 'course')
;
$query = $qb->getQuery();
return $query->getSingleScalarResult();
}
答案 9 :(得分:0)
您还可以使用计数功能获得数据数量。
$query = $this->dm->createQueryBuilder('AppBundle:Items')
->field('isDeleted')->equals(false)
->getQuery()->count();