How to use KNPPaginatorBundle to paginate results using Doctrine Repository?

こ雲淡風輕ζ 提交于 2019-12-31 22:09:09

问题


I'm working on a Symfony2 project and I decided to use KNPPaginatorBundle to build an easy pagination system. So I created a Product entity and I want to add the paginator to indexAction action (generated by CRUD command).

// Retrieving products.
$em = $this->getDoctrine()->getManager();

//$entities = $em->getRepository('LiveDataShopBundle:Product')->findAll();

$dql   = "SELECT a FROM LiveDataShopBundle:Product a";
$entities = $em->createQuery($dql);

// Creating pagnination
$paginator  = $this->get('knp_paginator');
$pagination = $paginator->paginate(
    $entities,
    $this->get('request')->query->get('page', 1),
    20
);

It works fine but I want to use the Product's repository instead of creating the query directly in the controller. How can I do that ? In fact, directly add the collection of results to the paginate object is just too slow because its load all products then paginate the ArrayCollection.

Thanks in advance.

K4


回答1:


I suggest using QueryBuilder in your ProductRepository and then passing that to the paginator:

ProductRepository extends EntityRepository
{
    // This will return a QueryBuilder instance
    public function findAll()
    {
        return $this->createQueryBuilder("p");
    }
}

In the controller:

$products = $productRepository->findAll();

// Creating pagnination
$paginator  = $this->get('knp_paginator');
$pagination = $paginator->paginate(
    $products,
    $this->get('request')->query->get('page', 1),
    20
);



回答2:


I think in some cases we could use Closure and pass to it a QueryBuilder object.

In your ProductRepository you could do something like this:

ProductRepository extends EntityRepository
{
    public function findAllPublished(callable $func = null)
    {
        $qb = $this->createQueryBuilder('p');

        $qb->where('p.published = 1');

        if (is_callable($func)) {
            return $func($qb);
        }

        return $qb->getQuery()->getResult();
    }
}

and then in ProductController:

public function indexAction(Request $request)
{
    $em = $this->get('doctrine.orm.entity_manager');
    $paginator = $this->get('knp_paginator');

    $func = function (QueryBuilder $qb) use ($paginator, $request) {
        return $paginator->paginate($qb, $request->query->getInt('page', 1), 10);
    };
    $pagination = $em->getRepository('AppBundle:Report')->findAllPublished($func);

    // ...
}

I think it more flexible and you could use findAllPublished method to get both paginated or NOT paginated results if you need.

Also keep in mind that callable type hint work in PHP >=5.4! Please, check docs for more info.




回答3:


In our project we want to avoid using Doctrine queries in controllers. We have also separate layers. Controllers must not access the database. So I included pagination in the Repository.

Here my code in controller:

public function indexAction(Request $request)
{
    $userRepository = $this->get('user_repository');
    $page = intval($request->query->get('page', 1));
    $pages = 0;
    $users = $userRepository->findAllPaginated($pages, $page - 1, 10);

    return $this->render('User:index.html.twig', array(
        'users' => $users,
        'page' => $page,
        'pages' => $pages,
    ));
}

And here is the important code in my repository:

use Doctrine\ORM\Tools\Pagination\Paginator;
class UserRepository extends EntityRepository
{
    /**
     * @return User[]
     */
    public function findAllPaginated(&$pages, $startPage = 0, $resultsPerPage = 5)
    {
        $dql = 'SELECT u FROM CoreBundle:User u';
        $query = $this->getEntityManager()->createQuery($dql)
            ->setFirstResult($startPage * $resultsPerPage)
            ->setMaxResults($resultsPerPage);

        $paginator = new Paginator($query);
        $count = $paginator->count();
        $pages = floor($count/$resultsPerPage);

        return $paginator; // on $paginator you can use "foreach", so we can say return value is an array of User
    }
}


来源:https://stackoverflow.com/questions/22804158/how-to-use-knppaginatorbundle-to-paginate-results-using-doctrine-repository

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!