Magento 2: ObjectManager को सीधे उपयोग करने या न करने के लिए?


134

ठीक है, इसलिए कल हमने कक्षाओं / टेम्पलेट्स के प्रत्यक्ष उपयोग केObjectManager बारे में मैगेंटो समुदाय के अन्य लोगों के साथ एक बड़ी बातचीत की ।

मैं पहले से ही उन कारणों से अवगत हूं कि हम एलन केंट के हवाले से सीधे ObjectManager का उपयोग क्यों नहीं करें :

इसके कई कारण हैं। कोड काम करेगा, लेकिन ObjectManager वर्ग को सीधे संदर्भित नहीं करना सबसे अच्छा अभ्यास है।

  • क्योंकि हम ऐसा कहते हैं! ;-) (बेहतर कोड के रूप में व्यक्त किया गया अच्छा कोड है)
  • कोड का उपयोग भविष्य में एक अलग निर्भरता इंजेक्शन ढांचे के साथ किया जा सकता है
  • परीक्षण आसान है - आप एक आवश्यक ऑब्जेक्ट प्रबंधक प्रदान किए बिना, आवश्यक वर्ग के लिए नकली तर्क में पास होते हैं
  • यह निर्भरता को स्पष्ट रखता है - यह स्पष्ट है कि कोड कोड के बीच में छिपी निर्भरता होने के बजाए, निर्माता सूची के माध्यम से निर्भर करता है
  • यह प्रोग्रामर्स को इनकैप्सुलेशन और मॉडर्लाइजेशन जैसी अवधारणाओं के बारे में सोचने के लिए प्रोत्साहित करता है - अगर कंस्ट्रक्टर बड़ा हो जाता है, तो शायद यह एक संकेत है कि कोड को रिफैक्टिंग करने की आवश्यकता है

मैंने StackExchange में जो देखा है, उससे बहुत सारे लोग उदाहरण के लिए आसान / संक्षिप्त / अनुशंसित नहीं समाधान के लिए जाते हैं:

<?php 
//Get Object Manager Instance
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

//Load product by product id
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($id);

इसके बजाय दर्दनाक लेकिन अनुशंसित प्रक्रिया से गुजरने के बाद :

  • एक मॉड्यूल बना रहा है
  • वरीयताएँ घोषित करना
  • निर्भरता को इंजेक्ट करें
  • एक सार्वजनिक विधि घोषित करें

हालाँकि, और यहाँ दुविधा आती है, Magento 2 कोर फाइलें अक्सर ObjectManager को सीधे कॉल करती हैं । एक त्वरित उदाहरण यहां पाया जा सकता है: https://github.com/magento/magento2/blob/develop/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php4L57

तो यहाँ मेरे सवाल हैं:

  • क्यों Magento कर रही है वे हमें क्या नहीं करने के लिए सलाह देते हैं? क्या इसका मतलब यह है कि कुछ मामले हैं जहां हमें ObjectManagerसीधे उपयोग करना चाहिए ? यदि हां, तो वे मामले क्या हैं?
  • सीधे ObjectManager का उपयोग करने के परिणाम क्या हैं ?

4
: इस की जाँच करें magento.stackexchange.com/q/28617/146
मेरियस

3
प्रासंगिक लिंक: mwop.net/blog/2016-04-26-on-locators.html । यह प्रासंगिक सा होगा The intent of zend-servicemanager is for use as an Inversion of Control container. It was never intended as a general purpose service locator [...]। यह M2 पर भी लागू होता है। इसके अलावा, There are valid use casesअनुभाग की जांच करें , जो फिर से, यहां भी लागू होता है।
नेवरमाइंड

3
एम 2 के विकास की कुछ अवधि थी जब ओम पहले से ही था, लेकिन कंस्ट्रक्टर इंजेक्शन का उपयोग करने के लिए पूरे मैगनेटो को अभी तक नहीं बदला गया था। उस बिंदु पर कई लोगों ने Mage की जगह ले ली: getSingleton () ObjectManager :: getInstance () -> get () के साथ। उस समय इस तरह के अधिकांश प्रयोग शुरू किए गए थे। बाद में सभी Mage :: getSingleton () कॉल को एक टूल द्वारा कंस्ट्रक्टर इंजेक्शन के साथ बदल दिया गया था, लेकिन टूल ने ObjectManager :: getInstance () को मान्यता नहीं दी थी, इसलिए इसे कंस्ट्रक्टर इंजेक्शन से प्रतिस्थापित नहीं किया।
एंटोन क्रिल


3
@TejabhagavanKollepara क्या आपने दोनों प्रश्न पढ़े हैं? समान हैं लेकिन एक-दूसरे से डुप्लिकेट होने से बहुत दूर हैं
राफेल एट डिजिटल पियानोवाद

जवाबों:


98

आपको सीधे ObjectManager का उपयोग नहीं करना चाहिए!

नियम से अपवाद हैं:

  • की तरह स्थिर जादू तरीकों में __wakeup, serialize, आदि
  • अगर आपको कंस्ट्रक्टर की बैकवर्ड संगतता बनानी चाहिए
  • वैश्विक दायरे में, एकीकरण परीक्षण के जुड़नार की तरह।
  • कक्षा में जिसे केवल फैक्ट्री, प्रॉक्सी, आदि जैसे ऑब्जेक्ट के निर्माण की आवश्यकता होती है

2
मुझे पता है कि मुझे इसे कभी भी सीधे उपयोग नहीं करना चाहिए लेकिन मैगेंटो ऐसा क्यों कर रहा है? ^ ^
डिजिटल पियानोवाद पर राफेल

2
आपके उदाहरण में पिछड़ी अनुकूलता के लिए है
KAndy

क्या उन लोगों को हमेशा @deprecated के रूप में चिह्नित किया जाता है?
राफेल डिजिटल पियानोवाद


5
ओह, हाँ, मैं जानता हूँ कि यह भ्रामक है। हो सकता है कि उन्होंने कहा था कि "ऐसा मत करो लेकिन इस बात से अवगत
रहो

53

जब हम इसके खिलाफ सलाह देते हैं तो M2 कभी-कभी ऑब्जेक्ट मैनेजर तक सीधे क्यों पहुंचता है?

क्रूर उत्तर: एम 2 एम 1 का एक बंदरगाह है - पूर्ण पुनर्लेखन नहीं। तो यह मत समझिए कि सभी M2 कोड पूरी तरह से अभी तक (दुर्भाग्य से) पोर्ट किए गए हैं। सिर्फ इसलिए कि आपको M2 कोड बेस में कुछ मिलता है, इसका मतलब यह नहीं है कि "यह करने का सबसे अच्छा तरीका है"। कभी-कभी यह सिर्फ "हम अभी तक इसे ठीक करने के लिए चारों ओर नहीं मिला है"।

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

बस अच्छी पेरेंटिंग सलाह को याद रखें: "बच्चे, जो मैं कहता हूं, वह करो, न कि मैं जो करता हूं!"


9
उत्कृष्ट उद्धरण: बच्चों, मैं जो कहता हूं, वही करो जो मैं नहीं करता हूं!
शिवकुमार

ऐसा नहीं है कि यह
किद्दो

क्या कोई Magento 2 वस्तु प्रबंधक के बिना एक नरम निर्भरता समस्या का तरीका सुझाता है? मेरे पास दूसरे पर नरम निर्भरता वाला एक मॉड्यूल है (यदि मॉड्यूल मौजूद है तो यह दूसरे वर्ग को लोड करता है)। मैं उस वर्ग को डीआई नहीं कर सकता क्योंकि तब डीआई विफल हो जाएगा। मैं उस वर्ग के लिए एक कारखाना भी नहीं बना सकता क्योंकि कारखाना DI में विफल हो जाएगा।
नाथन मेरिल

50

आपको कभी भी उपयोग नहीं करना चाहिए \Magento\Framework\App\ObjectManager::getInstance()
यह निर्भरता इंजेक्शन के उद्देश्य को हराता है। हम वापस आ गए Mage::getModel()
ऑब्जेक्ट मैनेजर का उपयोग केवल कारखानों में किया जाना चाहिए और फिर एक निर्माता में इंजेक्ट किया जाना चाहिए।

इसका उपयोग करने का लाभ लिखने के लिए कम कोड है। लेकिन यह इसे ठीक नहीं करता है।
तथ्य यह है कि यह अभी भी कोर में प्रयोग किया जाता है, क्योंकि यह अभी तक refactored नहीं मिला है। मुझे उम्मीद है कि यह होगा


5
तो हम दोनों सहमत हैं कि Magento कोड सही गलत कर रहा है?
राफेल डिजिटल पियानोवाद

11
सही। वे गलत हैं :)।
मारियस

मुझे नहीं लगता कि वे गलत उपयोग कर रहे हैं। आवश्यक होने पर वे इसका उपयोग कर रहे हैं: जब गतिशील समाधान की आवश्यकता होती है (प्लगइन्स, विशेष रूप से) और जब तुरंत-पदावनत तरीकों पर बीसी रखते हैं।
नेवरमाइंड

2
@nevvermind किसी कारखाने का उपयोग करना। आप di.xmlएक कुंजी => वर्ग नाम मानचित्र बनाने के लिए उपयोग करते हैं और उस मानचित्र को कारखाने के निर्माता को इंजेक्ट करते हैं और कारखाने का उपयोग ऑब्जेक्टमैनेजर के माध्यम से कक्षा को तुरंत करने के लिए करते हैं
Marius

2
@nevvermind लेकिन एक Magento कर्मचारी की राय आपकी राय का विरोध करती है। आपके पास KAndy से ऊपर एक उत्तर है जो बोल्ड पत्र में कहता है "आपको ऑब्जेक्ट प्रबंधक का सीधे उपयोग नहीं करना चाहिए": magento.stackexchange.com/a/117103/146 मुझे लगता है कि इस मुद्दे पर कोहरे को साफ करता है।
मेरियस

22

क्यों Magento कर रही है वे हमें क्या नहीं करने के लिए सलाह देते हैं? क्या इसका मतलब है कि कुछ ऐसे मामले हैं जहाँ हमें ObjectManager को सीधे इस्तेमाल करना चाहिए? यदि हां, तो उन मामलों का क्या?

यहाँ पूरी कहानी जाने बिना मेरा अनुमान है:

M2 के विकास के दौरान किसी चरण में Magento टीम एक स्वचालित स्क्रिप्ट जो की घटनाओं को प्रतिस्थापित भाग गया Mage:getModel(), Mage::getSingleton(), $layout->createBlock(), आदि ObjectManager उपयोग करने के लिए।

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

इसके अलावा Magento टीम हाल ही में एक भागने तंत्र के रूप में उपयोग करने के लिए लगता है। मौजूदा कार्यान्वयन को तोड़ने के बजाय (निर्माणकर्ता को बदलने की आवश्यकता के द्वारा) वे बस ObjectManager के माध्यम से नई निर्भरता को छिपाते हैं। मैं नहीं कह सकता कि मैं इस दृष्टिकोण से सहमत हूं - बीसी ब्रेक से बचने के लिए बदतर कोड लिखना।

सीधे ObjectManager का उपयोग करने के प्रत्यक्ष परिणाम क्या हैं?

मुझे लगता है कि आपके प्रश्न में पहले से ही पर्याप्त कारण शामिल हैं। आम तौर पर यह एक छिपी निर्भरता बनाता है, दूसरे शब्दों में निर्भरता कार्यान्वयन विवरण में होती है और अकेले कंस्ट्रक्टर से दिखाई नहीं देती है।


यह विडंबना है क्योंकि बीसी जनता के लिए जारी करने से पहले इसे ठीक से किया गया था, ऐसा कोई मुद्दा नहीं था
रॉबी एवरिल

12

सीधे वस्तु प्रबंधक का उपयोग नहीं करना चाहिए!

उदाहरण के लिए:

\Magento\Framework\App\ObjectManager::getInstance();

अगर आप इवेंट ऑब्जर्वर या प्लगइन्स के साथ काम कर रहे हैं, तो भी आपको इसका इस्तेमाल कभी नहीं करना चाहिए।

आप इसे फैक्ट्रियों में उपयोग कर सकते हैं, लेकिन इसके अलावा आपको पहले कंस्ट्रक्टर में ऑब्जेक्ट मैनेजर को इंजेक्ट करना चाहिए फिर आप अपनी विधि में इसके ऑब्जेक्ट का उपयोग कर सकते हैं

उपयोग करने के लिए पसंदीदा:

1) निजी वस्तु घोषित करें:

private $_objectManager;

2) कंस्ट्रक्टर में इंजेक्ट करें और आरंभ करें:

public function __construct(
    \Magento\Framework\ObjectManagerInterface $objectmanager
) {
    $this->_objectManager = $objectmanager;
}

3) किसी विधि में उपयोग करें:

public function create() {
    return $this->_objectManager->create(/* ......... */);
}

यह उत्तर मैगेंटो 2.2 संस्करणों के नीचे है, इसलिए कृपया ध्यान दें। नए Magento 2 मानकों के अनुसार अब हम ऑब्जेक्ट मैनजर उदाहरण का भी उपयोग नहीं कर सकते हैं। हमें किसी भी डेटा को प्राप्त करने के लिए ऑब्जेक्ट क्लास या रिपॉजिटरी के कारखाने का उपयोग करना होगा।


क्या इस तरह इसका इस्तेमाल करना अच्छा अभ्यास है?
enrico69

हां, क्योंकि Magento प्रत्यक्ष ऑब्जेक्ट मैनजर का उपयोग करने की अनुमति नहीं देता है, इसलिए आपको इस तरह से उपयोग करना होगा!
रौनक चौहान

आपको इसे कभी भी ईवेंट में उपयोग नहीं करना चाहिए (मुझे लगता है कि आपको ऑब्जर्वर का मतलब है) और प्लगइन्स। आपको ऑब्जेक्ट की आवश्यकता है, न कि ObjectManager को इंजेक्ट करना चाहिए। केवल एक कारखाने में आप ::getInstance()
ObjectManager का

राइट, उत्तर को संपादित करें @ 7ochem
रौनक चौहान

downvote किसी भी उत्तर का एक उपयुक्त तरीका नहीं है, यदि आपके पास बेहतर ज्ञान है तो आप अपना स्वयं का उत्तर जोड़ सकते हैं या आप किसी अन्य के उत्तर को बेहतर विचार प्राप्त करने और दूसरों के लिए उपयोगी बनाने के लिए संपादित कर सकते हैं। @ 7ochem
रौनक चौहान

10

सीधे तौर पर ऑब्जेक्ट मैनेजर का उपयोग करने से डेवलपर्स को दृढ़ता से हतोत्साहित किया जाता है इसका मुख्य कारण यह है कि ऑब्जेक्ट मैनेजर के प्रत्यक्ष उपयोग से एक्सटेंशन को संकलित रिलीज़ मोड में इंस्टॉल करने योग्य नहीं होने का कारण बनता है।

तो यह आपके ग्राहकों के लिए विमोचन मोड का उपयोग करके विराम देता है, जिसमें Magento Cloud के सभी ग्राहक शामिल हैं।

ऐसा लगता है कि डेवलपर्स का एक बहुत बड़ा अनुपात (लगभग 75%) यह देखने के लिए उनके एक्सटेंशन का परीक्षण नहीं करता है कि क्या उन्हें रिलीज़ मोड में स्थापित किया जा सकता है, इसलिए गलत ऑब्जेक्ट मैनजर के उपयोग से उत्पन्न मुद्दों में न चलें।

2017 तक, मैगेंटो मार्केटप्लेस इसके माध्यम से बेचे जाने वाले सभी एक्सटेंशन पर एक संकलन और इंस्टॉल परीक्षण चलाता है। यदि आपका एक्सटेंशन ऑब्जेक्ट मैनेजर का सीधे उपयोग करता है, तो यह इन परीक्षणों को विफल कर देगा और मार्केटप्लेस से तब तक खारिज कर दिया जाएगा जब तक आप इस समस्या को हल नहीं करते और पुनः लोड नहीं करते।


2

आप ऑब्जेक्टमैनेजर का ऑब्जेक्ट बनाकर कोशिश कर सकते हैं और ऑब्जेक्टमैनेजर को सीधे उपयोग नहीं करना चाहिए

कुछ का उपयोग करें,

class Example extends \Magento\Framework\View\Element\Template
{
    private $_objectManager;

    public function __construct(
        \Magento\Framework\ObjectManagerInterface $objectmanager
    ){
        $this->_objectManager = $objectmanager;
    }

    public function getExample()
    {
        $customerSession = $this->_objectManager->create("Magento\Customer\Model\Session");
        if ($customerSession->isLoggedIn()) {
            $customerData = $customerSession->getCustomer()->getData();
            /*Your logic*/
        }
    }
}

2
यदि ऑब्जेक्ट मैनेजर एक सिंगलटन है, तो इससे फर्क क्यों पड़ेगा?
डोमडम्ब्रोगिया
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.