W twoim przypadku to nie pagerfanta wykonuje pod-zapytania. Jest to źródło, z którego pochodzi instancja konstruktora zapytań.
Zwykle mam funkcję w repozytorium jednostek, która zwraca instancję zwykłego konstruktora kwerendy zamiast wyników. Pozostaje Ci napisanie wydajnego narzędzia do tworzenia zapytań. Następnie przekazuję ten kreator zapytań do DoctrineORMAdapter.
Mam tę funkcję pomocnika, który używam w całym moich projektów:
/**
* Pass an array, entity or a custom QueryBuilder instance to paginate.
* Takes an array of parameters as a second argument.
* Default parameter values:
*
* $params = array(
* 'curPage' => 1,
* 'perPage' => 15,
* 'order' => 'DESC'
*);
*
* @param mixed $object
* @param array $params
*
* @return Pagerfanta
*/
public function paginate($object, $params = array())
{
if (is_array($object)) {
$adapter = new ArrayAdapter($object);
} elseif ($this->isEntity($object)) {
$qb = $this->em->createQueryBuilder()
->select('s')
->from($this->getEntityName($object), 's')
->orderBy('s.id', isset($params['order']) ? $params['order'] : 'DESC');
$adapter = new DoctrineORMAdapter($qb);
} elseif ($object instanceof QueryBuilder) {
$adapter = new DoctrineORMAdapter($object);
}
$pager = new Pagerfanta($adapter);
$pager->setMaxPerPage(isset($params['perPage']) ? $params['perPage'] : 15);
$pager->setCurrentPage(isset($params['curPage']) ? $params['curPage'] : 1);
return $pager;
}
Można przekazać tablicę, podmiot lub instancję kreator zapytań i powróci odpowiednio paginowane obiekt gotowy do użycia.
Zapewne wiesz jak to zrobić, ale w każdym razie, oto co mam w moim repozytorium jednostki - jedna funkcja zwraca instancję kwerend (Idealny dla pagerfanta), a drugi zwraca tablicę być wykorzystywane gdzie indziej:
public function getMessageQueryBuilder($campaignId, $eqCriteriaArray = array(), $neqCriteriaArray = array())
{
$qb = $this->createQueryBuilder('m');
$qb->select('m')
->leftJoin('m.campaign', 'c')
->leftJoin('m.sentBy', 'u')
->where($qb->expr()->eq('m.campaign', $campaignId));
foreach ($eqCriteriaArray as $property => $value) {
$qb->andWhere($qb->expr()->eq($property, $qb->expr()->literal($value)));
}
foreach ($neqCriteriaArray as $property => $value) {
$qb->andWhere($qb->expr()->neq($property, $qb->expr()->literal($value)));
}
return $qb->orderBy('m.id', 'DESC');
}
public function filterMessages($campaignId, $eqCriteriaArray = array(), $neqCriteriaArray = array())
{
return $this->getMessageQueryBuilder($campaignId, $eqCriteriaArray, $neqCriteriaArray)->getQuery()->getResult();
Potem połączyć te dwa, aby uzyskać rzeczywisty obiekt pagera:
$singleSmsPager = $this->pagerUtil->paginate(
$this->em->getRepository('TreasureForgeMessageBundle:Message')
->getMessageQueryBuilder(CcToolSender::CAMPAIGN_ID, array(), array('u.username' => 'admin')),
array(
'curPage' => $singleSmsPage,
'perPage' => 10
)
);
Jeśli pojawi się kod generujący niepotrzebnie skomplikowane zapytania, może należy napisać raport o błędzie na stronie projektu. – lxg