Magento 2 में एक कस्टम मॉडल लोड करने का सबसे अच्छा तरीका


15

क्योंकि मेरे लिए सही रास्ता खोजना मुश्किल था, नीचे आप मेरे द्वारा किए गए सर्वोत्तम अभ्यास को पा सकते थे। आनंद लें, यदि आवश्यक हो तो मेरी अंग्रेजी को सही करें और कहें कि मैं गलत हूं। :)

संपादित करें: ... और मुझे पता चला कि मैं किसी पहलू पर गलत था। इसलिए मैंने राफेल के उत्तरों के बाद मूल पोस्ट को अपडेट किया जिससे मुझे अधिक समझने में मदद मिली। उसे धन्यवाद !

नीचे इस्तेमाल अवधारणा :

यदि आप इन अवधारणाओं के साथ सहज हैं तो नीचे दिए गए कोड और स्पष्टीकरण को समझना आपके लिए आसान होगा:

  • इंजेक्शन निर्भरता ( $this->variableकोड में प्रत्येक चर इंजेक्शन के रूप में)
  • सेवा अनुबंध और रिपोजिटरी
  • फ़ैक्टरी

प्रसंग :

बस अधिक संदर्भ के लिए, कल्पना करें कि हमारे पास एक मॉड्यूल है जिसका निर्माण सही तरीके से किया गया है:

  • एक ब्लॉक वर्ग CustomBlock एक विधि से युक्त getCustomModel($id),
  • यह विधि परम में पारित आईडी के आधार पर एक CustomModel ऑब्जेक्ट लौटाती है,
  • CustomModel प्रकार में मॉडल के अनुरूप है \Vendor\Module\Model\CustomModel
  • यह मॉडल अपने संसाधन मॉडल (इन \Vendor\Module\Model\ResourceModel\CustomModel) के साथ आता है
  • और इसके भंडार (में \Vendor\Module\Model\CustomModelRepository) के साथ।

प्रश्न :

  • कस्टममॉडल ऑब्जेक्ट को लोड करने वाली सभी चीज़ों को जाने देने के लिए सबसे अच्छा अभ्यास क्या है?

आप load()एक CustomModel ऑब्जेक्ट से उपयोग नहीं कर सकते क्योंकि यह विधि पदावनत है।

अच्छा अभ्यास कहता है कि आपको कस्टममॉडल सेवा अनुबंध का उपयोग करना होगा। सेवा अनुबंध डेटा इंटरफेस (जैसे CustomModelInterface) और सेवा इंटरफेस (जैसे CustomModelRepositoryInterface) हैं। तो मेरा ब्लॉक इस तरह दिखता है:

/ ** @वर स्लाइडपरोसॉरिटीइंटरफेस * /
संरक्षित $ स्लाइडरिपोसिटरी;

/ **
 * कस्टमब्लॉक कंस्ट्रक्टर
 * ...
 * @param CustomModelRepositoryInterface $ customModelRepository
 * ...
 * /
सार्वजनिक समारोह __construct (
...
CustomModelRepositoryInterface $ customModelRepository
...
) {
    $ यह-> customModelRepository = $ customModelRepository;
}

सार्वजनिक समारोह getCustomModel ($ आईडी) {
    $ यह लौटाएँ-> customModelRepository-> get ($ id);
}

सबसे पहले, हम CustomModelRepositoryInterfaceकंस्ट्रक्टर में ऑब्जेक्ट को इंजेक्ट करते हैं और हम इसे अपनी getCustomModel()विधि में उपयोग करते हैं ।

कक्षा Api\CustomModelRepositoryInterfaceमें बहुत कुछ नहीं है। आम तौर पर (लेकिन कुछ भी रोकने आप अलग करने के लिए) आप बुनियादी तरीके घोषणा करेंगे: get, getList, save, delete, deleteById। इस विषय के उद्देश्य के लिए, नीचे केवल getविधि घोषणा है:

/**
 * Get info by id
 *
 * @param int $id
 * @return Data\CustomModelInterface
 * @throws \Magento\Framework\Exception\NoSuchEntityException
 */
public function get($id);

ठीक है, लेकिन अगर मेरे कस्टम निर्माता ने अपने ब्लॉक कंस्ट्रक्टर में निर्भरता इंजेक्शन द्वारा बुलाया है, तो कोड कहां है? इस सवाल के जवाब के लिए आपको मैगेंटो को समझाना होगा जहां इस इंटरफ़ेस को लागू करने वाला वर्ग ढूंढें। मॉड्यूल के etc / di.xml फ़ाइल में, आपको जोड़ना होगा:

<preference for="Vendor\Module\Api\CustomModelRepositoryInterface" type="Vendor\Module\Model\CustomModelRepository" />

इसलिए CustomModelRepositoryInterfaceक्लास एक सर्विस इंटरफेस है। इसे लागू करने में आपको डेटा इंटरफेस (कम से कम Vendor\Module\Api\Data\CustomModelInterfaceऔर Vendor\Module\Api\Data\CustomModelSearchResultsInterface) भी लागू करना होगा । आपके मॉडल को लागू करना होगा Vendor\Module\Api\Data\CustomModelInterfaceऔर <preference ... />आपके प्रत्येक इंटरफेस के लिए लाइनें जोड़ना होगा । अंत में किसी भी समय आप सेवा अनुबंध का उपयोग करते हैं, mySomethingInterfaceअब और नहीं में सोचें mySomething: मैगनेटो को di.xmlवरीयता तंत्र का उपयोग करने दें ।

ठीक है, आगे क्या आता है? जैसे ही हम CustomModelRepositoryInterfaceब्लॉक कंस्ट्रक्टर में इंजेक्ट करते हैं, हमें एक CustomModelRepositoryऑब्जेक्ट मिलता है। CustomModelRepositoryमें घोषित विधि को लागू करना है CustomModelRepositoryInterface। तो हम इस में है Vendor\Module\Model\CustomModelRepository:

सार्वजनिक समारोह ($ आईडी) {
    $ customModel = $ this-> customModelFactory-> create ();
    $ CustomModel-> लोड ($ आईडी);
    अगर ($ customModel-> getId ()) {
      नई NoSuchEntityException (__ ""% 1 "आईडी के साथ कस्टममॉडल मौजूद नहीं है। ', $ id);
    }
    $ customModel वापस;
}

हम क्या कर रहे हैं ? हम CustomModelकारखाने के लिए एक खाली वस्तु धन्यवाद बनाते हैं । अगला हम लोड CustomModelमॉडल विधि का उपयोग करके डेटा लोड करते हैं। इसके बाद हम वापस लौटते हैं NoSuchEntityExceptionअगर हम CustomModelपरम में आईडी के साथ लोड करने में विफल रहे । लेकिन अगर सब कुछ ठीक है, तो हम मॉडल ऑब्जेक्ट वापस करते हैं और जीवन जारी रहता है।

लेकिन वाह ...! इस उदाहरण में वह क्या है?

$customModel->load($id);

loadशुरुआत से ही एक ही पदावनत विधि नहीं है ? हाँ यही है। मुझे लगता है कि यह शर्म की बात है, लेकिन आपको इसे इस लोड के बाद से उपयोग करना होगा () विधि कुछ प्रेषण हैं और डेवलपर उनके लिए सुन सकता है (नीचे राफेल का जवाब देखें)।

भविष्य में, हम इकाई प्रबंधक द्वारा बचत करेंगे। यह एक नई मैगेंटो 2 अवधारणा के रूप में एक और कहानी है, लेकिन यदि आप एक आंख को छोड़ना चाहते हैं, तो एंटिटी मैनेजर सीएमएस पेज के संसाधन मॉडल (v2.1) में पहले से ही लागू है:

public function load(AbstractModel $object, $value, $field = null)
{
    $pageId = $this->getPageId($object, $value, $field);
    if ($pageId) {
        $this->entityManager->load($object, $pageId);
    }
    return $this;
}

जवाबों:


16

सर्वोत्तम अभ्यास: सेवा अनुबंध के माध्यम से

जब भी संभव हो, सेवा अनुबंध का उपयोग करने के लिए सबसे अच्छा अभ्यास हमेशा होता है। आप यहां कारणों की सूची पा सकते हैं: Magento 2: सेवा अनुबंधों का उपयोग करने के क्या लाभ हैं?

सेवा अनुबंध को लागू करने के तरीके के विवरण के लिए मेरा सुझाव है कि आप इस विषय की जाँच करें: Magento 2 में कस्टम मॉड्यूल के लिए सेवा अनुबंध कैसे लागू करें?

यदि कोई सेवा अनुबंध उपलब्ध नहीं है

यदि कोई सेवा अनुबंध उपलब्ध नहीं है, तो आपको मॉडल रिपॉजिटरी getविधि का उपयोग करना चाहिए । इस विधि का उपयोग करते हुए, आप CategoryRepositoryवर्ग के लिए उदाहरण के लिए magento कैशिंग प्रणाली से लाभान्वित होते हैं :

public function get($categoryId, $storeId = null)
{
    $cacheKey = null !== $storeId ? $storeId : 'all';
    if (!isset($this->instances[$categoryId][$cacheKey])) {
        /** @var Category $category */
        $category = $this->categoryFactory->create();
        if (null !== $storeId) {
            $category->setStoreId($storeId);
        }
        $category->load($categoryId);
        if (!$category->getId()) {
            throw NoSuchEntityException::singleField('id', $categoryId);
        }
        $this->instances[$categoryId][$cacheKey] = $category;
    }
    return $this->instances[$categoryId][$cacheKey];
}

पदावनत load()विधि

Magento 2 धीरे-धीरे मानक CRUD प्रणाली से दूर जा रहा है विरासत प्रणाली को गिराकर और नए 2.1 EntityManager का उपयोग करके रचना के माध्यम से इसे लागू करने पर आप यहां विवरण पा सकते हैं: Magento 2.1: इकाई प्रबंधक का उपयोग करना

इसके अलावा, मेरा सुझाव है कि आप इस दिलचस्प विषय को पदावनत CRUD विधियों के बारे में पढ़ें: सार मॉडल में पदावनत बचत और भार विधियाँ

संसाधन मॉडल लोड का उपयोग क्यों नहीं किया जा रहा है

मुख्य कारण यह है कि यदि आप संसाधन मॉडल loadविधि का उपयोग करते हैं , तो आप लोडिंग सिस्टम के कुछ महत्वपूर्ण भाग को छोड़ देंगे जो मॉडल में लागू किया गया है load, देखें Magento\Framework\Model\AbstractModel:

public function load($modelId, $field = null)
{
    $this->_beforeLoad($modelId, $field);
    $this->_getResource()->load($this, $modelId, $field);
    $this->_afterLoad();
    $this->setOrigData();
    $this->_hasDataChanges = false;
    $this->updateStoredData();
    return $this;
}

संसाधन मॉडल loadविधि को सीधे कॉल करने से निम्नलिखित प्रभाव पड़ेगा:

  • _beforeLoad कहा जाता है: इस प्रकार घटनाओं से पहले मॉडल लोड नहीं भेजा जाता है
  • _afterLoad कहा जाता है: इस प्रकार घटनाओं के बाद मॉडल लोड नहीं भेजा जाता है
  • संग्रहीत डेटा अपडेट नहीं किए जाते हैं जो विभिन्न समस्याओं का कारण बन सकते हैं (उदाहरण के लिए यदि आप कॉल करते prepareDataForUpdateहैं Magento\Framework\Model\ResourceModel\Db\AbstractDb)

धन्यवाद राफेल, आपके द्वारा कही गई हर बात समझ में आती है और मेरा ज्ञान पूरा करती है। लेकिन मुझे समझ नहीं आ रहा है कि कांडी टिप्पणी (उसके उत्तर के तहत) कि मारियस अपने कस्टम मॉड्यूल संसाधन मॉडल के लोड () पद्धति का उपयोग क्यों कर सकता है? यह [ Magento.stackexchange.com/questions/114929/… सार मॉडल में सहेजें और लोड करने के तरीके हैं]। कोई विचार ?
निकोलस PERNOT

@ नाइकोलसप्रेनॉट मूल रूप से कांडी बताते हैं कि लक्ष्य प्रत्येक मॉड्यूल के लिए SL (सेवा परत) है और यही वह है जो हर बार आपको एक इकाई को लोड करने की आवश्यकता होती है। मेरा सुझाव है कि आप उसका उल्लेख करते हुए टिप्पणी करें कि शायद वह आपका ज्ञानवर्धन कर सकेगा क्योंकि वह एक
मैगेंटो

खैर, मैंने आखिरकार अपनी मूल पोस्ट को अपडेट कर दिया। आपकी मदद के लिए धन्यवाद राफेल।
निकोलस परनोट

मैं देखता हूं कि कम से कम मैगेंटो 2.2 में यह महत्वपूर्ण संसाधनमॉडल के लोड में शामिल है, इसलिए सीधे संसाधनमॉडल विधियों का उपयोग करना ठीक नहीं है, है ना?
जानिस एल्मेरिस

वर्तमान में, हम संसाधन मॉडल load()विधि का उपयोग करके मॉडल को सुरक्षित रूप से लोड कर सकते हैं । रिसोर्स मॉडल खुद के तरीके से मॉडल के तरीकों को कहता है load(): $model->beforeLoad() { $this->_beforeLoad() }और$model->afterLoad() { $this->_afterLoad() }
sergei.sss

-2

मुझे लगता है कि निम्नलिखित कथन अभी मान्य नहीं है।

Why not using the resource model load

हम Magento\Framework\EntityManager\Observerसभी घटनाओं को फ़ोल्डर पा सकते हैं ।

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