querybuilder query symfony doctrine2

symfony - Contar filas en Doctrine QueryBuilder



symfony doctrine get max value (9)

Agregar el siguiente método a su repositorio 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(); }

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



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


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


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


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