Count Строки в Doctrine QueryBuilder

Я использую QueryBuilder Doctrine для построения запроса, и я хочу получить общее количество результатов запроса.

$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 для разбивки на страницы).

    Что-то вроде:

     $qb = $entityManager->createQueryBuilder(); $qb->select('count(account.id)'); $qb->from('ZaysoCoreBundle:Account','account'); $count = $qb->getQuery()->getSingleScalarResult(); 

    РЕДАКТИРОВАТЬ

    Некоторые люди считают, что выражения как-то лучше, чем просто использование прямого DQL. Один даже дошел до того, чтобы отредактировать четырехлетний ответ. Я перевернул его обратно. Идите фигуру.

    Вот еще один способ отформатировать запрос:

     return $repository->createQueryBuilder('u') ->select('count(u.id)') ->getQuery() ->getSingleScalarResult(); 

    Лучше всего переместить всю логику работы с базой данных в репозитории.

    Поэтому в controllerе вы пишете

     $repository = $this->getDoctrine()->getRepository('FooBundle:Foo'); $count = $repository->count(); 

    И в FooBundle/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

    Если вам нужно посчитать более сложный запрос, с groupBy , having т. Д. Вы можете заимствовать у Doctrine\ORM\Tools\Pagination\Paginator :

     $paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($query); $totalRows = count($paginator); 

    Пример работы с группировкой, объединением и т. Д.

    Проблема:

      $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); 

    Чтобы подсчитать элементы после некоторого количества элементов (смещение), $ qb-> setFirstResults () не может быть применен в этом случае, поскольку он работает не как условие запроса, а как смещение результата запроса для выбранного диапазона элементов ( т.е. setFirstResult не может использоваться togather с 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; 

    Кто-нибудь знает более чистый способ сделать это?

    Для людей, которые используют только Doctrine DBAL, а не ORM Doctrine, они не смогут получить доступ к getQuery() поскольку он не существует. Им нужно сделать что-то вроде следующего.

     $qb = new QueryBuilder($conn); $count = $qb->select("count(id)")->from($tableName)->execute()->fetchColumn(0); 

    Начиная с Doctrine 2.6 можно использовать метод count() непосредственно из EntityRepository . Подробнее см. Ссылку.

    https://github.com/doctrine/doctrine2/blob/77e3e5c96c1beec7b28443c5b59145eeadbc0baf/lib/Doctrine/ORM/EntityRepository.php#L161

    Добавление следующего метода в ваш repository позволит вам вызвать $repo->getCourseCount() из вашего controllerа.

     /** * @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(); } 
    Давайте будем гением компьютера.