2014-04-02 11 views
10

मैं एक सिम्फनी 2 प्रोजेक्ट पर काम कर रहा हूं और मैंने एक आसान पेजिनेशन सिस्टम बनाने के लिए केएनपीपीजिनेटरबंडल का उपयोग करने का निर्णय लिया। इसलिए मैंने एक उत्पाद इकाई बनाई और मैं इंडेक्स एक्शन एक्शन (सीआरयूडी कमांड द्वारा जेनरेट) में पेजिनेटर जोड़ना चाहता हूं।डॉक्टर रेपोजिटरी का उपयोग करके परिणामों को पगनेट करने के लिए केएनपीपीजिनेटरबंडल का उपयोग कैसे करें?

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

यह ठीक काम करता है लेकिन मैं सीधे नियंत्रक में क्वेरी बनाने के बजाय उत्पाद की भंडार का उपयोग करना चाहता हूं। मैं उसे कैसे कर सकता हूँ ? वास्तव में, सीधे पेजिनेट ऑब्जेक्ट में परिणामों का संग्रह जोड़ना बहुत धीमा है क्योंकि यह सभी उत्पादों को लोड करता है तो फिर ऐरेकोलेक्शन को पगेट करता है।

अग्रिम धन्यवाद।

K4

+1

मैं भी इस प्रदर्शन मुद्दा देखा। समस्या यह है कि इस बंडल को अंकन उत्पन्न करने के लिए पूरे सरणी संग्रह की आवश्यकता होती है। यदि आप आंशिक परिणाम प्रदान करते हैं, तो पेजिनेशन में पृष्ठों की गलत संख्या होगी क्योंकि यह पूरे संग्रह से गणना की जाती है – Chopchop

उत्तर

16

मैं अपने ProductRepository में QueryBuilder का उपयोग कर और फिर से गुजर रहा सुझाव है कि 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 
); 
+0

धन्यवाद! मैंने किया, और यह ठीक काम करता है! लेकिन, createQuerybuilder() और createQuery() के बीच मौलिक अंतर क्या हैं? क्या मैं createNativeQuery() का उपयोग कर सकता हूं? – K4timini

+2

क्वेरी बनाएं जब आप स्वयं को DQL लिखना चाहते हैं, आमतौर पर आप ऐसा करेंगे जब क्वेरी पर्याप्त सरल हो। जब आप सशर्त के साथ जटिल प्रश्नों को बनाने की आवश्यकता होती है तो क्वेरीबिल्डर का उपयोग करें। तरल इंटरफ़ेस उस कार्य के लिए बहुत सुविधाजनक है। यही कारण है कि यह पेजिनेटर के साथ बहुत अच्छा काम करता है, क्योंकि QueryBuilder के साथ काम करना बहुत आसान है! –

+0

लेकिन यदि आप सभी का उपयोग करते हैं तो यह पहले सभी को एक प्रश्न में प्राप्त करेगा। क्या यह सच है? –

3

मैं कुछ मामलों में हम इस्तेमाल कर सकते हैं में लगता है Closure और इसे QueryBuilder ऑब्जेक्ट पास करें।

में अपने ProductRepository आप कुछ इस तरह कर सकता है: ProductController में

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

और उसके बाद:

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 विधि का उपयोग दोनों पृष्ठवार या नहीं प्राप्त करने के लिए कर सकता है यदि आपको आवश्यकता हो तो अंकुरित परिणाम।

यह भी ध्यान रखें कि callable PHP >=5.4 में संकेत संकेत टाइप करें! कृपया अधिक जानकारी के लिए docs देखें।

+0

स्मार्ट समाधान! – jmunozco

+0

@jmunozco धन्यवाद! लेकिन शायद सबसे अच्छा नहीं है;) दरअसल, यह समाधान आपको नियंत्रक में क्वेरी बिल्डर पर पूर्ण नियंत्रण प्राप्त करता है जो मुझे लगता है कि अच्छा नहीं है, यानी आपको इसे स्मार्ट का उपयोग करना चाहिए, लेकिन शायद कुछ और प्रतिबंधित है। –

0

हमारी परियोजना में हम नियंत्रकों में सिद्धांत क्वेरी का उपयोग करने से बचना चाहते हैं। हमारे पास अलग परतें भी हैं। नियंत्रकों को डेटाबेस तक नहीं पहुंचना चाहिए। तो मैं रिपोजिटरी में अंकन शामिल था।

यहाँ नियंत्रक में मेरी कोड:

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

जहां बिल्कुल $ पेज = मंजिल ($ count/$ resultsPerPage); प्रयोग किया जाता है? –

+0

क्या किसी को लगता है कि ऊपर की तरह $ paginator instanced एक बड़ा मुद्दा, प्रदर्शन या अन्यथा है - इसे एक सेवा के रूप में खींचने का विरोध है, जिसके लिए आपको किसी भी तरह से reppory वर्ग में knp_paginator सेवा इंजेक्ट करने की आवश्यकता होगी? – userfuser

संबंधित मुद्दे

 संबंधित मुद्दे