2014-04-02 16 views
10

Symfony2 projesi üzerinde çalışıyorum ve kolay bir sayfalandırma sistemi oluşturmak için KNPPaginatorBundle kullanmaya karar verdim. Bu yüzden bir Ürün varlığı oluşturdum ve paginator'i indexAction eylemine eklemek istiyorum (CRUD komutuyla oluşturuldu).Doctrine Repository kullanarak sonuçları sıralamak için KNPPaginatorBundle nasıl kullanılır?

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

Düzgün çalışır ama denetleyicisi doğrudan sorgu oluşturmak yerine Ürünün depo kullanmak istiyorum. Bunu nasıl yapabilirim ? Aslında, doğrudan tümüyle yüklenen nesneler ArboldCollection'ı sayfalandırdığı için, doğrudan paginate nesnesine sonuçların toplanmasını ekler.

Şimdiden teşekkürler.

K4

+1

Ben de bu performans sorununu fark ettim. Sorun, bu paketin sayfa dizisini oluşturmak için tüm dizi koleksiyonuna ihtiyaç duymasıdır. Kısmi bir sonuç verirseniz, tüm koleksiyondan hesaplandığı için sayfalandırma yanlış sayıda sayfaya sahip olacaktır – Chopchop

cevap

16

Ben geçen ardından ProductRepository içinde QueryBuilder kullanarak ve düşündürmektedir paginator için: denetleyici olarak

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

Teşekkürler! Ben yaptım ve iyi çalışıyor! Ancak, createQueryBuilder() ve createQuery() arasındaki temel farklar nelerdir? createNativeQuery() kullanabilir miyim? – K4timini

+2

DQL kendiniz yazmak istediğinizde sorgu oluşturmaktır, normalde sorgu yeterince basit olduğunda bunu yaparsınız. Koşullu karmaşık sorguları oluşturmanız gerektiğinde, queryBuilder'ı kullanın. Akışkan arayüzü bu görev için çok uygundur. QueryBuilder ile çalışmak çok kolay olduğu için bu yüzden, paginator ile harika çalışıyor! –

+0

Ancak, tümünü bulursanız, öncelikle bir sorguda her şeyi alırsınız. Bu doğru mu? –

3

biz kullanabiliriz bazı durumlarda düşünmek Closure ve ona bir QueryBuilder nesnesine iletin. Gelen

senin ProductRepository böyle bir şey yapabileceğini:

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

    // ... 
} 

ben daha esnek düşünmek ve sayfalandırılmaktadır veya DEĞİL hem olsun findAllPublished yöntemi kullanabilirsiniz: ProductController sonra

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

ve İhtiyacınız varsa paginated sonuçlar.

Ayrıca callable tip ipucunun PHP >=5.4'da çalıştığını unutmayın! Daha fazla bilgi için lütfen docs'a bakın.

+0

Akıllı çözüm! – jmunozco

+0

@jmunozco'ya teşekkürler! Ama muhtemelen en iyisi değil;) Aslında, bu çözüm, iyi bir düşüncede olmayan bir denetleyicide sorgu oluşturucu üzerinde tam kontrole sahip olur, yani akıllıca kullanmalı, ama muhtemelen daha kısıtlı bir şey yapmalısınız. –

0

Projemizde kontrolörlerde Doktrin sorgularını kullanmaktan kaçınmak istiyoruz. Ayrı katmanları da var. Denetleyiciler veritabanına erişmemelidir. Bu yüzden Deposu'nda sayfalama dahil ettim. denetleyicisi

İşte

kodum: Burada

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

Ve depoda önemli kodudur:

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

Tam olarak nerede $ sayfaları = kat ($ count/$ resultsPerPage); kullanıldı? –

+0

Yukarıdaki gibi yukarıda bahsettiğimiz $ paginator'ın büyük bir sorun, performans veya başka bir şey olduğunu düşünen biri var mı? Bunu bir hizmet olarak çekmeye karşı çıktınız, bunun için bir şekilde knp_paginator hizmetini depo sınıfına enjekte etmeniz gerekiyor mu? – userfuser