Contar filas en Doctrine QueryBuilder

Estoy usando Doctrine’s QueryBuilder para crear una consulta, y quiero obtener el recuento total de los resultados de la consulta.

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

Solo quiero ejecutar un conteo en esta consulta para obtener el total de filas, pero no devolver los resultados reales. (Después de esta consulta de conteo, voy a modificar aún más la consulta con maxResults para la paginación).

    Algo como:

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

    EDITAR

    Algunas personas sienten que las expresiones son de alguna manera mejor que solo usar DQL directo. Uno incluso llegó a editar una respuesta de cuatro años. Le devolví su edición. Imagínate.

    Aquí hay otra forma de formatear la consulta:

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

    Es mejor mover toda la lógica del trabajo con la base de datos a los repositores.

    Entonces en el controlador escribes

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

    Y en FooBundle/Repository/FooRepository.php

     public function count() { $qb = $repository->createQueryBuilder('t'); return $qb ->select('count(t.id)') ->getQuery() ->getSingleScalarResult(); } 

    Es mejor mover $qb = ... para separar la fila en caso de que quiera hacer expresiones complejas como

     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(); } 

    También piense en el almacenamiento en caché del resultado de su consulta: 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(); } 

    En algunos casos simples que usan relaciones de entidades EXTRA_LAZY es bueno
    http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/tutorials/extra-lazy-associations.html

    Si necesita contar una consulta más compleja, con groupBy , having etc … Puede tomar prestado de Doctrine\ORM\Tools\Pagination\Paginator :

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

    Ejemplo de trabajo con agrupación, unión y otras cosas.

    Problema:

      $qb = $em->createQueryBuilder() ->select('m.id', 'rm.id') ->from('Model', 'm') ->join('m.relatedModels', 'rm') ->groupBy('m.id'); 

    Para que esto funcione, la solución posible es usar un hidratador personalizado y esta cosa extraña llamada ‘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); 

    Para contar elementos después de cierto número de elementos (desplazamiento), $ qb-> setFirstResults () no se puede aplicar en este caso, ya que no funciona como una consulta, sino como un resultado de consulta para un rango de elementos seleccionados ( es decir, setFirstResult no se puede usar para registrar con COUNT en absoluto). Entonces, para contar los artículos que quedan, simplemente hice lo siguiente:

      //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; 

    ¿Alguien sabe más forma limpia de hacerlo?

    Para las personas que solo usan Doctrine DBAL y no Doctrine ORM, no podrán acceder al método getQuery() porque no existe. Necesitan hacer algo como lo siguiente.

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

    Desde Doctrine 2.6 , es posible utilizar el método count() directamente desde EntityRepository . Para más detalles, vea el enlace.

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

    Agregar el siguiente método a su repository debería permitirle llamar $repo->getCourseCount() desde su Controlador.

     /** * @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(); }