私は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を使用してクエリをさらに変更します。)
何かのようなもの:
$qb = $entityManager->createQueryBuilder();
$qb->select('count(account.id)');
$qb->from('ZaysoCoreBundle:Account','account');
$count = $qb->getQuery()->getSingleScalarResult();
編集
何人かの人々は、式は単純なDQLを使うよりもどうにか良いと感じています。 4歳の答えを編集することさえした。私は彼の編集を元に戻しました。図に行きます。
これは、クエリをフォーマットするための別の方法です。
return $repository->createQueryBuilder('u')
->select('count(u.id)')
->getQuery()
->getSingleScalarResult();
データベースを扱うすべてのロジックをリポジトリに移すことをお勧めします。
だからコントローラであなたが書く
/* 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
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);
Doctrine 2.6
以降、EntityRepository
から直接count()
メソッドを使用することが可能です。詳細についてはリンクを参照してください。
Doctrine DBALのみを使用し、Doctrine ORMを使用していない人にとっては、getQuery()
メソッドが存在しないためアクセスできません。彼らは以下のようなことをする必要があります。
$qb = new QueryBuilder($conn);
$count = $qb->select("count(id)")->from($tableName)->execute()->fetchColumn(0);
ある数のアイテム(offset)の後のアイテムを数えるために、$ 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;
誰かがそれを行うためのよりクリーンな方法を知っていますか?
以下のメソッドをあなたのリポジトリに追加すると、あなたのコントローラから$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();
}