2012-02-08 15 views
15

में एक्सेस रिपोजिटरी फ़ंक्शंस मान लें कि मेरे डेटाबेस में दो टेबल हैं: खरगोश और गाजर। खरगोशों में 0 या गुणक गाजर हो सकते हैं और एक गाजर एक खरगोश से संबंधित होता है। यह उन दो तालिकाओं के बीच 1, एन संबंध है।Symfony2 - इकाई

मेरे पास दो इकाइयां, खरगोश और गाजर हैं।

मेरे पास मेरे टेम्पलेट में पारित खरगोशों की एक श्रृंखला है और मैं प्रत्येक खरगोश से विशिष्ट गाजर उन्हें एक डिस्प्ले प्राप्त करना चाहता हूं: मान लीजिए कि मैं 10 और महंगी गाजर प्राप्त करना चाहता हूं (गाजर की कीमतें गाजर की मेज में संग्रहित की जाएंगी) सरणी में प्रत्येक $ खरगोश से।

कुछ की तरह:

{% for rabbit in rabbits %} 
    {% for carrot in rabbit.getMoreExpensiveCarrots %} 

     {{ carrot.price }} 

    {% endfor %} 
{% endfor %} 

मैं भंडार वर्ग का उपयोग कर रहा है, लेकिन अगर मैं एक समारोह getMoreExpensiveCarrots ($ खरगोश) एक खरगोश भंडार कक्षा में बनाने के लिए, मैं एक इकाई से है कि समारोह का उपयोग करने के लिए सक्षम नहीं होगा ऐसा वर्ग है, जो मैं चाहता:

$ rabbit-> getMoreExpensiveCarrots()

मैंने सोचा था कि ऐसा करने के लिए है कि एक तरह से एक getMoreExpensiveCarrots() बनाने के लिए खरगोश इकाई में होगा:

// Entity rabbit 
class Rabbit 
{ 
    public function getMoreExpensiveCarrots() 
    { 
     // Access repository functions like getMoreExpensiveCarrots($rabbit) 
     // But how can I do such thing ? Isn't that bad practise ? 
     return $carrots; 
    }   
} 

मैंने सोचा कि मैं कर सकता है और वह भी:

// Entity rabbit 
    class Rabbit 
    { 
     public function getMoreExpensiveCarrots() 
     { 
      $this->getCarrots(); 

      // Then try here to sort the carrots by their price, using php    

      return $carrots; 
     }   
    } 

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

public function indexAction() 
    { 
     $em = $this->getDoctrine()->getEntityManager(); 

     $rabbits = $em->getRepository('AppNameBundle:Rabbit')->getSomeRabbits(); 

     return $this->render('AppNameBundle:Home:index.html.twig', 
       array(
        "rabbits"=>$rabbits 
     )); 
    } 

सबसे अच्छा अभ्यास टेम्पलेट में प्रत्येक खरगोश से एक getMoreExpensiveCarrots समारोह कॉल करने के लिए क्या है?

धन्यवाद!

+4

मुझे इस खरगोश और गाजर की चीज़ें पसंद हैं।<3 –

उत्तर

8

मूल बातें पर वापस जाएं। भंडार बनाम सेवा के बारे में भूल जाओ और खरगोशों और गाजर पर ध्यान केंद्रित करें।

class Rabbit 
{ 
/** @ORM\OneToMany(targetEntity="Carrot", mappedBy="rabbit" */ 
protected $carrots; 

public function getCarrots() { return $this->carrots; } 

public function getMoreExpensiveCarrots() 
{ 
    // Get all carrots 
    $carrots = $this->getCarrots()->toArray(); 

    // Sort by price 
    // http://php.net/manual/en/function.usort.php 
    usort(&$carrots,array($this,'compareTwoCarrotsByPrice')); 

    // Now slice off the top 10 carrots (slice - carrots, hah, kindo of funny 
    $carrots = array_slice($carrots, 0, 10); 

    // And return the sorted carrots 
    return $carrots; 
} 
public function compareTwoCarrotsByPrice($carrot1,$carrot2) 
{ 
    if ($carrot1->getPrice() > $carrot2->getPrice()) return -1; 
    if ($carrot1->getPrice() < $carrot2->getPrice()) return 1; 
    return 0; 
} 
} 

अपनी गाड़ी से सभी गाजर सामान हटाएं और केवल खरगोशों की एक सूची प्राप्त करें।
आपका मूल टेम्पलेट अब वास्तव में काम करेंगे के रूप में उम्मीद:

{% for rabbit in rabbits %} 
    {% for carrot in rabbit.getMoreExpensiveCarrots %} 

     {{ carrot.price }} 

    {% endfor %} 
{% endfor %} 

यहाँ केवल नकारात्मक पक्ष यह है कि प्रत्येक खरगोश के लिए, सभी गाजर के लिए एक अलग क्वेरी स्वचालित रूप से सिद्धांत द्वारा उत्पन्न हो जाएगा। कुछ बिंदु पर प्रदर्शन में बाधा डाली जाएगी। जब आप उस बिंदु तक पहुंचते हैं तो आप अपनी मूल क्वेरी पर वापस जा सकते हैं और देख सकते हैं कि गाजर को अधिक कुशलता से कैसे लाया जाए। लेकिन उपर्युक्त वर्ग पहले काम कर रहा है क्योंकि मुझे लगता है कि यह आपका अवरुद्ध बिंदु हो सकता है।

+0

धन्यवाद! चूंकि यह $-> getCarrots() ourayCollection को आउटपुट करता है, मुझे "usort() पैरामीटर 1 को सरणी होने की अपेक्षा करता है, ऑब्जेक्ट दिया जाता है" ... मैं इसे डीबग करने का प्रयास करूंगा। – httpete

+1

आश्चर्य की बात है कि usort एक लागू कार्यान्वयन Iterator संभाल नहीं कर सकता है। किसी भी घटना में: $ गाजर = $ यह-> getCarrots() -> toArray(); – Cerad

+0

ओह आदमी, यह अंत में काम कर रहा है \ o/बहुत बहुत धन्यवाद :) – httpete

7

आपकी इकाई कक्षाओं को केवल उस वस्तु के बारे में ध्यान रखना चाहिए जो वे प्रतिनिधित्व करते हैं, और पूरी तरह से इकाई प्रबंधक या भंडारों का कोई ज्ञान नहीं है।

एक संभावित समाधान यहां एक सेवा ऑब्जेक्ट (RabbitService) का उपयोग करना है जिसमें getMoreExpensiveCarrots विधि शामिल है। सेवा को इकाई प्रबंधक और भंडारों के बारे में जानने की अनुमति है, इसलिए यह यहां है कि आप कोई जटिल परिचालन करते हैं।

सेवा ऑब्जेक्ट का उपयोग करके, आप चिंताओं को अलग करते रहते हैं, और यह सुनिश्चित करते हैं कि आपकी इकाई कक्षाएं उस नौकरी को करें जो उनका मतलब है, और कुछ भी नहीं।

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

+0

तो मैं उस सेवा को अपनी संस्था खरगोश से बुलाऊंगा? – httpete

+0

आप नियंत्रक से अलग सेवा को अलग से कॉल करेंगे। –

+1

मुझे खेद है, मैं एक नौसिखिया हूं और मुझे इस मामले में रिपॉजिटरीज और सेवा के बीच अंतर को समझ में नहीं आता है क्योंकि मुझे इसे नियंत्रक से कॉल करना है :(मैं अपने नियंत्रक से getMoreExpensiveCarrots को कॉल नहीं करना चाहता, लेकिन मेरे टेम्पलेट में प्रत्येक $ खरगोश से। असल में मेरे नियंत्रक में, मैं अपने खरगोशों को पाने के लिए यही करता हूं: $ खरगोश = $ em-> getRepository ('AppNameBundle: Rabbit') -> getSomeRabbits(); अब कैसे होना चाहिए मैं सेवा के getMoreExpensiveCarrots को कॉल करता हूं? – httpete

7

मुझे इसे समझाने में एक शॉट लेने दें। सिद्धांत 2 ओआरएम को थोड़ा सा पुनर्विचार की आवश्यकता होती है। वर्तमान में आपके पास मानसिकता है कि खरगोश को जब भी इसकी ज़रूरत होती है तो उसके गाजर से पूछने में सक्षम होना चाहिए। आपको उस मानसिकता को बदलने की जरूरत है।

सिद्धांत 2 के लिए, विचार है कि जब आप खरगोश बनाते हैं तो खरगोशों को अपने गाजर देना होगा। दूसरे शब्दों में, यह क्वेरी समय पर किया जाता है। धारणा यह है कि खरगोशों के लिए डेटाबेस से पूछताछ की प्रक्रिया जो भी प्रक्रिया जानता है वह जानता है कि आप गाजर का एक विशिष्ट सेट भी चाहते हैं।

इस मामले में आप 10 सबसे महंगी गाजर चाहते हैं ताकि आपकी प्रक्रिया को यह जानना आवश्यक हो। तो अब आप @Arms उत्तर पर वापस जाएं और खुद को एक खरगोश प्रबंधक सेवा बनाएं जिसे loadRabbitsWithExpensiveCarrots कहा जाता है। वापसी मूल्य उनके गाजर पहले से भरने वाले खरगोशों की एक सरणी होगी।

टिप्पणियों को संबोधित करने के लिए इसे अपडेट किया गया।

  1. सिद्धांत 2 भंडार बनाम Symfony 2 सेवा

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

एक सिम्फनी 2 सेवा आपके खरगोशों और गाजरों के आयोजन के बारे में सभी विवरण छुपाती है। यह एक और सामान्य अवधारणा है और कई इकाइयों को शामिल करने वाले जटिल जटिल प्रश्नों से निपट सकती है। यह एस 2 का मूल भवन ब्लॉक है और आपको वास्तव में इसके साथ आराम करने की आवश्यकता है।

आपकी वर्तमान आवश्यकता के लिए, या तो दृष्टिकोण काम करेगा।

  1. गाजर परम सवाल

अभी तक सुनिश्चित नहीं है कि वास्तव में क्या मतलब है। शायद आप नमूना पूछताछ पोस्ट कर सकते हैं? ध्यान रखें कि आप निश्चित रूप से अपने खरगोश वस्तु को एक getExpensiveCarrots() विधि जोड़ सकते हैं। विधि getCarrots() को कॉल करना शुरू हो जाएगा। वापस गाजर पहले से ही प्रारंभिक क्वेरी द्वारा लोड किया गया होगा। आपकी विधि फ़िल्टर और सॉर्ट करेगा।

और ध्यान रखें कि हम उस मामले से निपटने की कोशिश कर रहे हैं जहां खरगोश के पास सैकड़ों या हजारों गाजर संलग्न हो सकते हैं। तो हम केवल प्रदर्शन विचार के लिए सभी गाजर लोड करने से बचने की कोशिश कर रहे हैं। प्रारंभिक क्वेरी में गाजर को लोड नहीं करना शुरू करना आसान हो सकता है। इसके बजाए, पहली बार आपके खरगोश-> getCarrots() को कॉल किया जाता है, सिद्धांत 2 स्वचालित रूप से एक प्रश्न जारी करेगा और उस खरगोश के लिए सभी गाजर लोड करेगा। और फिर एक बार फिर आपका getExpensiveCarrots विधि आवश्यकतानुसार फ़िल्टर और सॉर्ट करेगा।

इस सहायता की आशा करें। शायद आपको और भी भ्रमित कर दिया।

+0

ठीक है, मदद के लिए धन्यवाद, अब मैं बेहतर समझ सकता हूं कि यह कैसे काम कर सकता है। लेकिन फिर भी, मैं इसे सचमुच काम करने के लिए प्रबंधित नहीं कर सकता;) इसमें कोई फ़ंक्शन बनाने के बीच क्या अंतर होगा खरगोश भंडार loadRabbitsWithExpensiveCarrots ($ खरगोश = $ em-> getRepository ('AppNameBundle: Rabbit') -> loadRabbitsWithExpensiveCarrots();) और एक ही चीज़ को करने के लिए एक सेवा का उपयोग कर? प्लस मैं पैरामीटर द्वारा आदेशित मेरे खरगोश को पुनः प्राप्त करने के लिए क्वेरी नहीं कर पाऊंगा और साथ ही ऑर्डर गाजर मूल्य से भी कर सकता हूं। – httpete

+0

मैंने आपके लिए एक जवाब जोड़ा :) http://stackoverflow.com/a/9251217/668157 – httpete