2011-08-15 10 views
6

मैं किसी इकाई में क्वेरी कैसे कर सकता हूं?सिद्धांत 2, इकाइयों के अंदर क्वेरी

namespace Entities\Members; 

/** 
* @Entity(repositoryClass="\Entities\Member\MembersRepository") 
* @Table(name="Members") 
* @HasLifecycleCallbacks 
*/ 
class Members extends \Entities\AbstractEntity 
{ 
    /** 
    * @Id @Column(name="id", type="bigint",length=15) 
    * @GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @Column(name="userid", type="bigint", length=26, nullable=true) 
    */ 
    protected $userid; 

    /** 
    * @Column(name="fname", type="string", length=255,nullable=true) 
    */ 
    protected $fname; 

    /** 
    * @OneToMany(targetEntity="\Entities\Users\Wall", mappedBy="entry", cascade={"persist"}) 
    */ 
    protected $commententries; 

    public function __construct() 
    { 
     $this->commententries = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 
} 

उदाहरण मैं इस इकाई कहा जाता है के अंदर एक समारोह करना चाहते हैं: filter() और मैं फिल्टर करने के लिए commententries संग्रह सक्षम होना चाहते हैं। इसे एक निश्चित स्थिति जैसे id=1 के साथ एक संग्रह वापस करना चाहिए। असल में यह शामिल क्वेरी से प्राप्त डेटा को फ़िल्टर करना चाहिए।

तो कुछ इस तरह:

$this->commententries->findBy(array('id' => 1)); 

लेकिन स्पष्ट रूप से यह काम नहीं करता।

+0

आप एक कस्टम रिपोजिटरी का उपयोग कर ऐसा कर सकते हैं जिसे आपने पहले से ही @Entity (repositoryClass = "\ Entities \ Member \ MembersRepository") का उपयोग करके परिभाषित किया है। नीचे मेरा उत्तर देखें: http://stackoverflow.com/a/19319313/1697459 – Wilt

उत्तर

12

आम तौर पर, आपको यह नहीं करना चाहिए।

अंगूठे के नियम के रूप में संस्थाओं को इकाई प्रबंधक (सीधे, या कुछ मध्यस्थ वस्तु के माध्यम से) के बारे में पता नहीं होना चाहिए।

इसका कारण अधिकतर टेस्टेबिलिटी है, लेकिन मेरे अनुभव में, यह चीजों को अन्य तरीकों से व्यवस्थित रखने में मदद करता है।

मैं आपके लिए लुकअप को संभालने वाली सेवा कक्षा तैयार करके इसे संपर्क करूंगा। आपका नियंत्रक (या जो भी) इस तरह यह ड्राइव करेंगे:

<?php 
// create a new service, injecting the entitymanager. if you later wanted 
// to start caching some things, you might inject a cache driver as well. 
$member = $em->find('Member',$member_id); //get a member, some how. 
$svc = new MemberService($em); 

$favoriteCommentaries = $svc->getFavoriteCommentaries($member); 

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

getFavoriteCommentaries() विभिन्न कार्यान्वयन का उपयोग कर सकता है। एक मामूली व्यक्ति इसे सदस्य :: getFavoriteCommentaries() में प्रॉक्सी करना होगा, जो वास्तव में सबकुछ लोड करेगा, और फिर "पसंदीदा" को फ़िल्टर करेगा। यह शायद विशेष रूप से अच्छी तरह से स्केल नहीं करेगा, इसलिए आप केवल उस डेटा को लाने के लिए ईएम का उपयोग करके इसे बेहतर बना सकते हैं।

1

आपका प्रश्न वास्तव में समझना मुश्किल था, कृपया भविष्य में अपने प्रश्नों को कैसे व्यवस्थित करें, इस पर प्रयास करें और कार्य करें। उदाहरण के लिए, आप कहते हैं "एक ही परिणाम वापस लौटें" लेकिन "फ़िल्टर", जिसका अर्थ कुछ भी हो सकता है। क्या आप एक ही परिणाम सेट का उपयोग करना चाहते हैं (आप पृथ्वी पर क्यों ऐसा करना चुनेंगे), और केवल परिणामों को फ़िल्टर करने के लिए array_filter या array_walk का उपयोग करें या आप वास्तव में एक सशर्त जुड़ना चाहते हैं? यह अविश्वसनीय रूप से संदिग्ध है।

वैसे भी .. उत्तर (अपना प्रश्न 4 बार पढ़ने के बाद)।

$q = $qb->select ("m","w") 
      ->from ("Members", "m") 
      ->leftJoin("m.commententries","w",'WITH', 'w.id = :id') 
      ->setParameter ("id", $id) 
      ->getQuery(); 
+0

क्या आप इकाई इकाई में array_filter का उपयोग कर सकते हैं? मैंने कोशिश की: array_filter ($ ए, सरणी ("सदस्य", "एंट्रीफिल्टर")); लेकिन कक्षा नहीं मिली। –

+0

यदि आप अपने getResult() को हाइड्रेशन मोड सरणी के रूप में वापस कर रहे थे तो आप कर सकते थे। यह किसी भी सरणी पर कदम उठाने की तरह होगा। -> getQuery() -> getResult (2) यह करेगा। – Layke

21

आपका ऐरेकॉलेक्शन पहले से ही फ़िल्टर() विधि लागू करता है, आपको अपनी इकाइयों (यहां, टिप्पणी एंटर्रीज़) को काम करने के लिए क्लोजर पास करने की आवश्यकता है।

$idsToFilter = array(1,2,3,4); 

$member->getComments()->filter(
    function($entry) use ($idsToFilter) { 
     if (in_array($entry->getId(), $idsToFilter)) { 
      return true; 
     } 

     return false; 
    } 
); 

(परीक्षण नहीं)

ध्यान दें कि इस तरह के विधि पुनरावृति जाएगा और अधिक अपने सभी टिप्पणियां उत्सुक लोड, मामले में जहां एक उपयोगकर्ता एक बहुत यह एक बड़ा टोंटी हो सकता है में तो;

ज्यादातर मामलों में, आप कस्टम रिपॉजिटरीज़ का उपयोग करना चाहते हैं, जहां आप ऐसे तर्क डाल सकते हैं।

जैसा कि timdev ने सुझाव दिया है, आप सदस्य सेवा बना सकते हैं जो EntityManager से अवगत होकर इस तरह के कॉल को लपेट लेगा।

पेरिसेंस परत से पृथक इकाइयां सिद्धांत 1 पर एक बड़ा सुधार है, और आपको उस नियम को तोड़ना नहीं चाहिए।

+1

php बंद करने में आपको कोष्ठक के साथ चर संलग्न करना होगा उदा। उपयोग करें ($ idsToFilter) – falinsky

+0

@falinsky धन्यवाद, संपादित। –

1

मैं "timdev" से सहमत हूं। आपको अपनी संस्था वर्ग में क्वेरी को परिभाषित नहीं करना चाहिए। एक सेवा वर्ग को परिभाषित करने का मेरा तरीका संस्थाओं को भंडार वर्ग हैं। उदाहरण के लिए: उपयोगकर्ता (इकाई - आपकी बंडल/Entity/User.php) में UserRepository (सेवा श्रेणी - आपका बंडल/रिपोजिटरी/UserRepository.php) होगा। आपकी "फ़िल्टर" विधि यहां होनी चाहिए। आपको बस अपनी इकाई वर्ग में इस सेवा वर्ग को मैप करने की आवश्यकता है। अपने नियंत्रक में, आप हमेशा अपने भंडार के माध्यम से "फ़िल्टर" तक पहुंच सकते हैं। यह Symfony2 book

4

में बहुत विस्तार दस्तावेज़ीकरण किया गया है प्रश्नों

आप अपने सत्ता के बारे में प्रश्नों नहीं लिखना चाहिए के लिए एक कस्टम भंडार का उपयोग करें, लेकिन आप उस के लिए भंडार का उपयोग करना चाहिए। यह सिद्धांत दस्तावेज 7.8.8 Custom Repositories में भी समझाया गया है। यह आपको केंद्रीय स्थान पर अपने कस्टम प्रश्नों को बनाने की अनुमति देगा और आपकी इकाई परिभाषाओं को साफ रखेगा।

उपयोग फिल्टर संग्रह करने के लिए मापदंड:

लेकिन आप Criteria उपयोग कर सकते हैं अगर आप एक get विधि में अपने संग्रह के अंदर फ़िल्टर करना चाहते हैं। आप पढ़ सकते हैं कि को डॉक्टरेट दस्तावेज 8.8 Filtering collections में कैसे उपयोग करें। फ़िल्टर करने के लिए लगता है कि यह कुछ ऐसा दिखाई देगा क्या करना चाहते हैं:

public function getCommentEntries() 
{ 
    $criteria = Criteria::create() 
     ->where(Criteria::expr()->eq('id', 1)); 

    $filteredCommentEntries = $this->commententries->matching($criteria); 

    return $filteredCommentEntries; 
} 
: फिल्टर करने के लिए वर्ग का उपयोग अपने इकाई वर्ग के शीर्ष पर

प्रचार अपने getCommentEntries विधि में Criteria वर्ग

use Doctrine\Common\Collections\Criteria 

+0

@deanjase मैं लंबे समय बाद फिर से समाप्त हुआ और देखा कि पहले यह स्पष्ट नहीं था कि आप अपने संग्रह को फ़िल्टर करना चाहते हैं। मैंने अपना जवाब अपडेट किया क्योंकि आपके संग्रह 'get' विधि में फ़िल्टरिंग निश्चित रूप से संभव है। – Wilt

+0

हालांकि उत्तर पुराना है, मुझे फ़िल्टरिंग संग्रह दस्तावेज में यह छोटा नोट मिला है, जो कहता है "आप किसी इकाई के समर्पित तरीकों में संग्रहों के स्लाइसों तक पहुंच को स्थानांतरित कर सकते हैं। उदाहरण के लिए समूह # getTodaysBirthdayUsers()। जो स्पष्ट रूप से EntityManager को आपके लिए दृश्यमान बना रहा है इकाई। क्या यह नियम तोड़ नहीं रहा है? " –

+0

@AftabNaveed आप इस विधि को अपनी इकाई में जोड़ते समय EntityManager का पर्दाफाश नहीं करेंगे। उदाहरण में उन्हें '$ userCollection' एकत्र करने के लिए पहले' $ समूह' मिलता है। आपकी समूह इकाई में आप बस अपने कस्टम गेटर के अंदर '$ this-> getUsers();' कर सकते हैं और फिर मानदंड तर्क जोड़ सकते हैं। – Wilt

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