2012-10-08 12 views
15

मैं कम से कम 2 बाएं जुड़ने के साथ एक जटिल अनुरोध को पगनेट करना चाहता हूं, लेकिन पेजिनेशन बंडल जिसका उपयोग मैं कर रहा हूं (एनपीपीग्नेशनबंडल) सिद्धांत को नहीं बता सकता है कि परिणाम कैसे गिनें (which is needed for the pagination process), और इस अपवाद को जारी रखें।सिद्धांत: बाएं के साथ अंकन

Cannot count query which selects two FROM components, cannot make distinction

यहां नमूने के सिद्धांत QueryBuilder के साथ बनाया गया अनुरोध है।

public function findGroupsByUser(User $user, $listFilter, $getQuery = false, $order = 'ASC') 
{ 
    $query = $this->createQueryBuilder('r') 
     ->select('r as main,g') 
     ->select('r as main,g, count(gg) as members') 
     ->leftjoin('r.group', 'g') 
     ->innerjoin('MyBundle:GroupMemberRel', 'gg', 'WITH', 'r.group = gg.group') 
     ->addGroupBy('g.groupId') 
     ->add('orderBy', 'g.name ' . $order); 
    if ($getQuery == true) { 
     return $query; 
    } 

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

तब मैं knp_paginator सेवा करने के लिए इस अनुरोध को अपवाद

$groupQuery = $this->em->getRepository('MyBundle:GroupMemberRel')->findGroupsByUser($user, $listFilter, true); 
    $paginator = $this->container->get('knp_paginator'); 
    /* @var $groups Knp\Component\Pager\Pagination\PaginationInterface */ 
    $groups = $paginator->paginate(
     $groupQuery, $this->container->get('request')->query->get('page', 1), 10 /* limit per page */ 
    ); 

कैसे एक जटिल अनुरोध से अधिक पृष्ठ पर अंक लगाना करने के लिए पर कोई विचार दे, और उसके बाद मुझे मिल गया है, मैं इस प्रयोग बहुत यकीन है कि -केस सामान्य है, पेजिनेशन के बाद मेरे परिणाम को हाइड्रेट नहीं करना चाहता।

+0

पेजरफंटा के सिद्धांत ओआरएम एडाप्टर पक्षियों के प्रश्नों को संभालने में सक्षम होना चाहिए। https://github.com/whiteoctober/Pagerfanta – AdrienBrault

+0

यह क्वेरी अजीब नहीं है, मुझे यकीन है कि इसे आसानी से knp paginator के साथ करने का कोई तरीका है, शायद मुझे knp पेजर –

+0

पर गहराई से देखना चाहिए इस समस्या का सामना करना .. कोई समाधान? – tttony

उत्तर

20

इस बारे में एक जवाब की तलाश में किसी को भी के लिए, वहाँ पर एक अच्छा समाधान है इसका उपयोग करने के लिए।

+5

दोस्तों, ** सरणी (' विशिष्ट '=> झूठी) ** नोट करें ... मुझे उम्र – Eugene

14

मूल प्रश्न में इकाइयों को समझना मुश्किल है, लेकिन मैं इस समस्या में भाग गया और यह वास्तव में हल करने योग्य था।

मान लीजिए कि आप इस तरह से एक इकाई है:

class User 
    { 
    // ... 
    /** 
    * @ORM\OneToMany(targetEntity="Registration", mappedBy="user") 
    */ 
    private $registrations; 
    // ... 
    } 

महत्वपूर्ण बात यह किसी अन्य संस्था के साथ एक एक-से-कई संबंध नहीं है कि है, और आप के माध्यम से है कि करने के लिए शामिल होने के लिए सक्षम होना चाहते हैं QueryBuilder किसी भी कारण से (उदाहरण के लिए, आप अपनी क्वेरी में HAVING क्लॉज जोड़ना चाह सकते हैं ताकि इन इकाइयों में से एक या अधिक इकाइयों को चुन सकें)।

आपका मूल कोड लग सकता है जैसे:

$qb = $this->createQueryBuilder(); 

    $query = $qb 
    ->select('u') 
    ->add('from', '\YourBundle\ORM\Model\User u') 
    ->leftJoin('\YourBundle\ORM\Model\Registration', 'r', 'WITH', 'u.id = r.user') 
    ->groupBy('u.id') 
    ->having($qb->expr()->gte($qb->expr()->count('u.registrations'), '1') 
    ->getQuery(); 

यह अपवाद फेंक देगा: Cannot count query which selects two FROM components, cannot make distinction

इसे ठीक करने के क्वेरी पुनर्लेखन ताकि QueryBuilder केवल घटक "से" एक है - वास्तव में क्योंकि अपवाद इंगित करता है - इनलाइन में शामिल होने से। इस तरह:

$qb = $this->createQueryBuilder(); 

    $query = $qb 
    ->select('u') 
    ->add('from', '\YourBundle\ORM\Model\User u LEFT JOIN u.registrations r') 
    ->groupBy('u.id') 
    ->having($qb->expr()->gte($qb->expr()->count('r'), '1') 
    ->getQuery(); 

किसी भी अन्य बंडलों के साथ, डॉक्टर के पेजिनेटर वर्ग के साथ ठीक काम करना चाहिए। शामिल होने पर शॉर्टंड सिंटैक्स भी ध्यान दें; सिद्धांत के साथ आप स्पष्ट रूप से शामिल इकाई को निर्दिष्ट करने के लिए नहीं देख रहे हैं (हालांकि आप कर सकते हैं) क्योंकि मानचित्रण पहले से ही जानता है कि यह क्या है।

उम्मीद है कि यह किसी की मदद करता है, वहां इस मुद्दे पर बहुत कुछ नहीं है। @halfer's comment here पर देखकर आंतरिक इसे कैसे प्रबंधित करते हैं, इसके बारे में आप और अधिक पढ़ सकते हैं। , https://github.com/KnpLabs/KnpPaginatorBundle/blob/master/Resources/doc/manual_counting.md

$paginator = new Paginator; 

$count = $entityManager 
->createQuery('SELECT COUNT(c) FROM Entity\CompositeKey c') 
->getSingleScalarResult(); 

$query = $entityManager 
->createQuery('SELECT c FROM Entity\CompositeKey c') 
->setHint('knp_paginator.count', $count); 

$pagination = $paginator->paginate($query, 1, 10, array('distinct' => false)); 

असल में, तुम क्या कर रहे आप अपने खुद के 'गणना' क्वेरी बनाने और KNP paginator हिदायत कर रहे हैं:

+3

से आता है यह स्वीकार्य उत्तर होना चाहिए! – newbie

+0

बस FYI @ भविष्यवाणी मैंने आपके सुझाव की कोशिश की लेकिन यह काम नहीं करता है। https://gist.github.com/TrkiSF2/16d64a8aec846f4053a5 दृष्टिकोण बदलने की अधिक आवश्यकता की जांच नहीं कर सकता :( – EnchanterIO

+0

ऐसा लगता है कि आपके पास जो समस्या है, वह शामिल होने से संबंधित नहीं है, बल्कि 'हैविंग' के उपयोग के लिए, जो कि इस प्रकार के उपयोग के साथ पेजिनेटर द्वारा समर्थित नहीं है। प्रदान किए गए कोड स्निपेट से, यह स्पष्ट नहीं है कि इरादा क्या है, लेकिन शायद आप केवल 1 या अधिक लॉगिन वाले उपयोगकर्ताओं को प्राप्त करने का प्रयास कर रहे हैं? यदि ऐसा है, तो बस '-> जहां 'हैहिंग' के स्थान पर '' lh.user शून्य नहीं है ') और इसे काम करना चाहिए। – futureal

0

जोड़ने के लिए मत भूलना अगर आप उपरोक्त उत्तरों में दिए गए तरीके से नियमित मैप किए गए इकाइयों के साथ काम नहीं कर रहे हैं, तो परिणाम परिणाम में अतिरिक्त घटक बनाएंगे। इसका मतलब है कि सेट को गणना नहीं की जा सकती क्योंकि यह स्केलर नतीजे नहीं है।

तो कुंजी आपके परिणाम सेट को एक घटक में रख रही है जो स्केलर परिणाम का उत्पादन और गणना करने की अनुमति देगा।

आप एक नियमित क्षेत्र को रन टाइम पर एक इकाई मैपिंग में परिवर्तित कर सकते हैं। यह आपको यादृच्छिक रूप से अन्य इकाइयों में शामिल होने के बावजूद केवल एक घटक के साथ प्रश्न लिखने की अनुमति देता है। एक अतिरिक्त रूट इकाई या परिणाम के अतिरिक्त घटक के विपरीत 'अन्य संस्थाएं' मुख्य इकाई का एक बच्चा बन जाती हैं।

नीचे दिया गया उदाहरण एक-से-एक मैपिंग दिखाता है। मैंने अधिक जटिल मैपिंग की कोशिश नहीं की है लेकिन इसके साथ मेरी सफलता से पता चलता है कि यह संभव होना चाहिए। पंजीकरण इकाई में उपयोगकर्ता नामक एक फ़ील्ड होता है जिसमें उपयोगकर्ता आईडी होती है, लेकिन यह मैप किए गए इकाई को केवल एक सादा फ़ील्ड नहीं है।

(यह एक काम कर उदाहरण से संशोधित किया गया है, लेकिन परीक्षण नहीं किया है के रूप में - तो छद्म कोड के रूप में इलाज)

$queryBuilder // The query builder already has the other entities added. 
     ->innerJoin('r.user', 'user') 
    ; 


    $mapping['fieldName'] = 'user'; 
    $mapping['targetEntity'] = '\YourBundle\ORM\Model\User'; 
    $mapping['sourceEntity'] = '\YourBundle\ORM\Model\Registration'; 
    $mapping['sourceToTargetKeyColumns'] = array('user' => 'id'); 
    $mapping['targetToSourceKeyColumns'] = array('id' => 'user'); 
    $mapping['fetch'] = 2; 
    $mapping['joinColumns'] = array(
     array(
      'name' => 'user', 
      'unique' => false, 
      'nullable' => false, 
      'onDelete' => null, 
      'columnDefinition' => null, 
      'referencedColumnName' => 'id', 
     ) 
    ); 
    $mapping['mappedBy'] = 'user'; 
    $mapping['inversedBy'] = null; // User doesn't have to link to registrations 
    $mapping['orphanRemoval'] = false; 
    $mapping['isOwningSide'] = true; 
    $mapping['type'] = ClassMetadataInfo::MANY_TO_ONE; 

    $vm = $this->em->getClassMetadata('YourBundle:Registration'); 

    $vm->associationMappings["user"] = $mapping; 

नोट: मैं PagerFanta उपयोग कर रहा था नहीं KNP - लेकिन समस्या यह सिद्धांत तो मैं के साथ निहित है उम्मीद है कि यह कहीं भी काम करेगा।

2

सिद्धांत के लिए डॉक्टर/डबल को अपडेट करना 2.5 मेरे लिए तय किया गया है।

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

  • कोई संबंधित समस्या नहीं^_^