Как использовать KNPPaginatorBundle для разбивки на страницы с использованием репозитория Doctrine?

Я работаю над проектом Symfony2, и я решил использовать KNPPaginatorBundle для создания простой системы разбиения на страницы. Поэтому я создал объект Product, и я хочу добавить paginator в действие indexAction (генерируемое командой CRUD).

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

Он работает нормально, но я хочу использовать репозиторий продукта вместо создания запроса непосредственно в контроллере. Как я могу это сделать ? Фактически, прямое добавление коллекции результатов в объект paginate является слишком медленным, потому что его загрузка всех продуктов затем разбивает на страницы ArrayCollection.

Заранее спасибо.

K4

Я предлагаю использовать QueryBuilder в вашем ProductRepository а затем передать это в paginator:

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

В контроллере:

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

Я думаю, что в некоторых случаях мы могли бы использовать Closure и передать ему объект QueryBuilder .

В вашем ProductRepository вы можете сделать что-то вроде этого:

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

а затем в 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); // ... } 

Я думаю, что он более гибкий, и вы можете использовать метод findAllPublished чтобы получить как findAllPublished на страницы, так и НЕ findAllPublished на страницы результаты, если вам нужно.

Также имейте в виду, что подсказка типа подсказки работает в PHP >=5.4 ! Пожалуйста, проверьте документы для получения дополнительной информации.

В нашем проекте мы хотим избежать использования запросов Doctrine в контроллерах. У нас также есть отдельные слои. Контроллеры не должны обращаться к базе данных. Поэтому я включил разбиение на страницы в репозитории.

Здесь мой код в контроллере:

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

И вот важный код в моем репозитории:

 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 } }