Magento 2 में एक कस्टम मॉड्यूल के लिए सेवा अनुबंध कैसे लागू करें?


42

के रूप में इस पोस्ट में देखी गई: पदावनत बचाने के लिए और सार मॉडल में लोड तरीकोंsave और loadतरीकों Magento 2 में पदावनत कर रहे हैं शाखा का विकास।

इस प्रकार, अच्छा अभ्यास अब CRUD संस्थाओं से निपटने के लिए सेवा अनुबंधों को लागू करना है।

मेरे कस्टम मॉड्यूल संस्थाओं के लिए सेवा अनुबंधों को लागू करने के लिए मुझे चरण-दर-चरण प्रक्रिया का पालन करने की आवश्यकता है?

NB: मुझे पता है कि मेरे CRUD मॉडल में हज़ारों विधियाँ हो सकती हैं, मैं यहाँ बताए गए स्पष्ट तरीकों के लिए कह रहा हूँ: http://devdocs.magento.com/guides/v2.0/extension-dev-guide /service-contracts/design-patterns.html :

  • get
  • save
  • getList
  • delete
  • deleteById

जवाबों:


89

मैं @ryanF के शानदार उत्तर के अलावा थोड़ा और विस्तार देना चाहूंगा।

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

अस्वीकरण: मैं केवल एक व्यावहारिक दृष्टिकोण का वर्णन कर रहा हूं कि यह तीसरे पक्ष के मॉड्यूल के लिए कैसे किया जाए - कोर टीमों के अपने मानक हैं जो वे अनुसरण करते हैं (या नहीं)।

सामान्य तौर पर, भंडार से संबंधित उद्देश्य भंडारण से संबंधित तर्क को छिपाना है।
एक रिपॉजिटरी के एक ग्राहक को यह ध्यान नहीं रखना चाहिए कि किसी सरणी में मेमोरी में रिटर्न की गई इकाई को किसी MySQL डेटाबेस से प्राप्त किया गया है, जिसे दूरस्थ एपीआई या फ़ाइल से लिया गया है।
मुझे लगता है कि मैगेंटो कोर टीम ने ऐसा किया ताकि वे भविष्य में ओआरएम को बदल सकें या बदल सकें। Magento में ORM में वर्तमान में मॉडल, संसाधन मॉडल और संग्रह शामिल हैं।
यदि कोई तृतीय पक्ष मॉड्यूल केवल रिपॉजिटरी का उपयोग करता है, तो Magento डेटा को कैसे और कहाँ संग्रहीत किया जाता है, और इन गहरे परिवर्तनों के बावजूद मॉड्यूल काम करना जारी रखेगा।

डेटा संग्रह स्थान आम तौर पर की तरह तरीकों findById(), findByName(), put()या remove()
मैगनेटो में आमतौर पर इन्हें बुलाया जाता है getbyId(), save()और delete()यह दिखावा भी नहीं किया जाता है कि वे कुछ और कर रहे हैं बल्कि CRUD DB ऑपरेशन भी कर रहे हैं।

Magento 2 रिपॉजिटरी विधियों को आसानी से एपीआई संसाधनों के रूप में उजागर किया जा सकता है, जिससे उन्हें थर्ड पार्टी सिस्टम या हेडलेस Magento उदाहरणों के साथ एकीकरण के लिए मूल्यवान बनाया जा सकता है।

"क्या मुझे अपनी कस्टम इकाई के लिए एक भंडार जोड़ना चाहिए?"।

हमेशा की तरह, जवाब है

"निर्भर करता है"।

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

एक और कारक है जो यहां गिनती में आता है: मैगेंटो 2 में, रिपॉजिटरी को आसानी से वेब एपीआई के रूप में उजागर किया जा सकता है - यह रीस्ट और सोप - संसाधन है।

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

मैं अपनी कस्टम इकाई के लिए एक भंडार कैसे जोड़ूँ?

यह मान लें कि आप अपनी संस्था को REST API के भाग के रूप में उजागर करना चाहते हैं। यदि यह सच नहीं है, तो आप इंटरफेस बनाने पर आगामी भाग को छोड़ सकते हैं और सीधे "रिपॉजिटरी और डेटा मॉडल कार्यान्वयन" को नीचे जा सकते हैं।

रिपॉजिटरी और डेटा मॉडल इंटरफेस बनाएँ

Api/Data/अपने मॉड्यूल में फ़ोल्डर्स बनाएं । यह केवल कन्वेंशन है, आप एक अलग स्थान का उपयोग कर सकते हैं, लेकिन आपको नहीं करना चाहिए।
रिपॉजिटरी Api/फ़ोल्डर में चला जाता है । Data/उपनिर्देशिका बाद के लिए है।

में Api/, उन तरीकों से एक PHP इंटरफ़ेस बनाएं, जिसे आप उजागर करना चाहते हैं। Magento 2 सम्मेलनों के अनुसार सभी इंटरफ़ेस नाम प्रत्यय में समाप्त होते हैं Interface
उदाहरण के लिए, एक Hamburgerइकाई के लिए, मैं इंटरफ़ेस बनाऊंगा Api/HamburgerRepositoryInterface

रिपॉजिटरी इंटरफ़ेस बनाएँ

Magento 2 रिपॉजिटरी एक मॉड्यूल के डोमेन लॉजिक का हिस्सा हैं। इसका मतलब यह है कि, रिपॉजिटरी को लागू करने के तरीकों का कोई निश्चित सेट नहीं है।
यह पूरी तरह से मॉड्यूल के उद्देश्य पर निर्भर करता है।

हालांकि, व्यवहार में सभी रिपॉजिटरी काफी समान हैं। वे CRUD कार्यक्षमता के लिए रैपर हैं।
अधिकांश तरीकों getById, save, deleteऔर getList
उदाहरण के लिए, CustomerRepositoryएक विधि हो सकती है get, जो एक ग्राहक को ईमेल द्वारा लाती है, जिसके getByIdद्वारा इकाई आईडी द्वारा एक ग्राहक को पुनः प्राप्त करने के लिए उपयोग किया जाता है।

यहाँ एक हैमबर्गर इकाई के लिए एक उदाहरण भंडार इंटरफ़ेस है:

<?php

namespace VinaiKopp\Kitchen\Api;

use Magento\Framework\Api\SearchCriteriaInterface;
use VinaiKopp\Kitchen\Api\Data\HamburgerInterface;

interface HamburgerRepositoryInterface
{
    /**
     * @param int $id
     * @return \VinaiKopp\Kitchen\Api\Data\HamburgerInterface
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function getById($id);

    /**
     * @param \VinaiKopp\Kitchen\Api\Data\HamburgerInterface $hamburger
     * @return \VinaiKopp\Kitchen\Api\Data\HamburgerInterface
     */
    public function save(HamburgerInterface $hamburger);

    /**
     * @param \VinaiKopp\Kitchen\Api\Data\HamburgerInterface $hamburger
     * @return void
     */
    public function delete(HamburgerInterface $hamburger);

    /**
     * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
     * @return \VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface
     */
    public function getList(SearchCriteriaInterface $searchCriteria);

}

जरूरी! यहाँ timesinks हो!
यहाँ कुछ गच हैं जो आपको गलत होने पर डिबग करने के लिए कठिन हैं:

  1. यदि आप इसे REST API में हुक करना चाहते हैं, तो PHP7 स्केलर तर्क प्रकारों या रिटर्न प्रकारों का उपयोग करें !
  2. सभी तर्कों और सभी प्रकार के रिटर्न प्रकार के लिए PHPDoc एनोटेशन जोड़ें!
  3. PHPDoc ब्लॉक में पूरी तरह से योग्य वर्ग नामों का उपयोग करें !

JSON या XML से डेटा को परिवर्तित करने के तरीके का निर्धारण करने के लिए एनोटेशन को Magento फ्रेमवर्क द्वारा पार्स किया जाता है। वर्ग आयात (अर्थात, useकथन) लागू नहीं होते हैं!

हर विधि में किसी भी तर्क प्रकार और वापसी प्रकार के साथ एक एनोटेशन होना चाहिए। यहां तक ​​कि अगर कोई विधि कोई तर्क नहीं देती है और कुछ भी नहीं लौटाती है, तो इसके लिए एनोटेशन होना चाहिए:

/**
 * @return void
 */

अदिश प्रकार ( string, int, floatऔर bool) भी निर्दिष्ट करने की बहस के लिए और एक वापसी मान के रूप में दोनों की है।

ध्यान दें कि ऊपर दिए गए उदाहरण में, ऑब्जेक्ट्स को वापस करने वाले तरीकों के एनोटेशन को इंटरफेस के रूप में भी निर्दिष्ट किया गया है।
वापसी प्रकार के इंटरफेस सभी Api\Dataनामस्थान / निर्देशिका में हैं।
यह इंगित करना है कि उनके पास कोई व्यावसायिक तर्क नहीं है। वे केवल डेटा के बैग हैं।
हमें आगे ये इंटरफेस बनाना होगा।

DTO इंटरफ़ेस बनाएँ

मुझे लगता है कि मैगेंटो इन इंटरफेस को "डेटा मॉडल" कहता है, एक ऐसा नाम जो मुझे बिल्कुल पसंद नहीं है।
इस प्रकार के वर्ग को आमतौर पर डेटा ट्रांसफर ऑब्जेक्ट या डीटीओ के रूप में जाना जाता है ।
इन डीटीओ वर्गों के पास केवल अपने सभी गुणों के लिए गेटर्स और सेटर हैं।

डेटा मॉडल पर DTO का उपयोग करने का कारण यह है कि ORM डेटा मॉडल, संसाधन मॉडल या दृश्य मॉडल के साथ भ्रमित करना कम आसान है ... बहुत सी चीजें पहले से ही Magento में मॉडल हैं।

PHP7 टाइपिंग के संबंध में समान प्रतिबंध जो कि रिपॉजिटरी पर लागू होते हैं, डीटीओ पर भी लागू होते हैं।
साथ ही, प्रत्येक विधि के पास सभी तर्क प्रकारों और रिटर्न प्रकार के साथ एनोटेशन होना चाहिए।

<?php

namespace VinaiKopp\Kitchen\Api\Data;

use Magento\Framework\Api\ExtensibleDataInterface;

interface HamburgerInterface extends ExtensibleDataInterface
{
    /**
     * @return int
     */
    public function getId();

    /**
     * @param int $id
     * @return void
     */
    public function setId($id);

    /**
     * @return string
     */
    public function getName();

    /**
     * @param string $name
     * @return void
     */
    public function setName($name);

    /**
     * @return \VinaiKopp\Kitchen\Api\Data\IngredientInterface[]
     */
    public function getIngredients();

    /**
     * @param \VinaiKopp\Kitchen\Api\Data\IngredientInterface[] $ingredients
     * @return void
     */
    public function setIngredients(array $ingredients);

    /**
     * @return string[]
     */
    public function getImageUrls();

    /**
     * @param string[] $urls
     * @return void
     */
    public function setImageUrls(array $urls);

    /**
     * @return \VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface|null
     */
    public function getExtensionAttributes();

    /**
     * @param \VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface $extensionAttributes
     * @return void
     */
    public function setExtensionAttributes(HamburgerExtensionInterface $extensionAttributes);
}

यदि कोई विधि किसी सरणी को प्राप्त या वापस लाती है, तो सरणी में आइटम के प्रकार को PHPDoc एनोटेशन में निर्दिष्ट किया जाना है, इसके बाद एक वर्ग को खोलने और बंद करने के लिए ब्रैकेट है []
यह अदिश मानों (जैसे int[]) के साथ-साथ वस्तुओं (उदाहरण IngredientInterface[]) दोनों के लिए सही है ।

ध्यान दें कि मैं Api\Data\IngredientInterfaceएक उदाहरण के रूप में वस्तुओं के एक सरणी को वापस करने के लिए उपयोग कर रहा हूं , मैं इस पोस्ट के अवयवों के कोड को कठिन नहीं जोड़ूंगा।

ExtensibleDataInterface?

ऊपर दिए गए उदाहरण HamburgerInterfaceमें ExtensibleDataInterface
तकनीकी रूप से यह केवल तभी आवश्यक है जब आप चाहते हैं कि अन्य मॉड्यूल आपकी इकाई में विशेषताओं को जोड़ने में सक्षम हों।
यदि हां, तो आपको एक और गेट्टर / सेटर जोड़ी भी मिलाने की जरूरत है, जिसे कन्वेंशन कहा जाता है getExtensionAttributes()और setExtensionAttributes()

इस विधि के रिटर्न प्रकार का नामकरण बहुत महत्वपूर्ण है!

Magento 2 फ्रेमवर्क इंटरफ़ेस, कार्यान्वयन और कार्यान्वयन के लिए कारखाना उत्पन्न करेगा यदि आप उन्हें सही नाम देते हैं। इन यांत्रिकी के विवरण इस पद के दायरे से बाहर हैं, हालांकि।
बस पता है, यदि आप जिस वस्तु को एक्स्टेंसिबल बनाना चाहते हैं \VinaiKopp\Kitchen\Api\Data\HamburgerInterface, उसके इंटरफेस को कहा जाता है , तो एक्सटेंशन विशेषताओं का प्रकार होना चाहिए \VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface। इसलिए शब्द Extensionको Interfaceप्रत्यय से ठीक पहले इकाई नाम के बाद डाला जाना चाहिए ।

यदि आप नहीं चाहते हैं कि आपकी इकाई एक्स्टेंसिबल हो, तो DTO इंटरफ़ेस को किसी अन्य इंटरफ़ेस को विस्तारित करने की आवश्यकता नहीं है, getExtensionAttributes()और setExtensionAttributes()विधियों को छोड़ा जा सकता है।

अभी के डीटीओ इंटरफ़ेस के बारे में पर्याप्त है, रिपॉजिटरी इंटरफ़ेस पर लौटने का समय।

GetList () वापसी प्रकार SearchResults

रिपॉजिटरी विधि getListअभी तक एक और प्रकार, SearchResultsInterfaceअर्थात् एक उदाहरण देता है।

विधि getListनिश्चित रूप से निर्दिष्ट वस्तुओं से मेल खाने वाली वस्तुओं की एक सरणी लौटा सकती है SearchCriteria, लेकिन एक SearchResultsउदाहरण को वापस करने से रिटर्न मानों में कुछ उपयोगी मेटा डेटा जोड़ने की अनुमति मिलती है।

आप देख सकते हैं कि रिपॉजिटरी getList()मेथड इम्प्लीमेंटेशन में कैसे काम करता है ।

यहाँ उदाहरण हैमबर्गर खोज परिणाम इंटरफ़ेस है:

<?php

namespace VinaiKopp\Kitchen\Api\Data;

use Magento\Framework\Api\SearchResultsInterface;

interface HamburgerSearchResultInterface extends SearchResultsInterface
{
    /**
     * @return \VinaiKopp\Kitchen\Api\Data\HamburgerInterface[]
     */
    public function getItems();

    /**
     * @param \VinaiKopp\Kitchen\Api\Data\HamburgerInterface[] $items
     * @return void
     */
    public function setItems(array $items);
}

यह सब इंटरफ़ेस है यह दो तरीकों getItems()और setItems()मूल इंटरफ़ेस के प्रकारों को ओवरराइड करता है ।

इंटरफेस का सारांश

अब हमारे पास निम्नलिखित इंटरफेस हैं:

  • \VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface
  • \VinaiKopp\Kitchen\Api\Data\HamburgerInterface
  • \VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface

भंडार कुछ भी नहीं फैली हुई है, फैली हुई है , और फैली हुई है ।
HamburgerInterface\Magento\Framework\Api\ExtensibleDataInterface
HamburgerSearchResultInterface\Magento\Framework\Api\SearchResultsInterface

रिपॉजिटरी और डेटा मॉडल कार्यान्वयन बनाएं

अगला कदम तीन इंटरफेस के कार्यान्वयन को बनाना है।

रिपोजिटरी

संक्षेप में, रिपॉजिटरी यह काम करने के लिए ORM का उपयोग करती है।

getById(), save() और delete()तरीकों काफी सीधे आगे हैं। , एक निर्माता तर्क के रूप में भंडार में इंजेक्ट किया जिसका नीचे एक सा देखा जा सकता है।
HamburgerFactory

public function getById($id)
{
    $hamburger = $this->hamburgerFactory->create();
    $hamburger->getResource()->load($hamburger, $id);
    if (! $hamburger->getId()) {
        throw new NoSuchEntityException(__('Unable to find hamburger with ID "%1"', $id));
    }
    return $hamburger;
}

public function save(HamburgerInterface $hamburger)
{
    $hamburger->getResource()->save($hamburger);
    return $hamburger;
}

public function delete(HamburgerInterface $hamburger)
{
    $hamburger->getResource()->delete($hamburger);
}

अब एक भंडार का सबसे दिलचस्प हिस्सा है, getList()विधि। विधि का अनुवाद करने में है संग्रह पर विधि कॉल में स्थिति।
getList()SerachCriteria

इस बात का मुश्किल हिस्सा हो रही है ANDऔर ORफिल्टर सही के लिए शर्तों, खासकर जब से संग्रह पर स्थिति की स्थापना के लिए वाक्य रचना कि क्या यह एक EAV या एक फ्लैट तालिका इकाई है के आधार पर अलग है।

ज्यादातर मामलों में, getList()नीचे दिए गए उदाहरण में सचित्र के रूप में लागू किया जा सकता है।

<?php

namespace VinaiKopp\Kitchen\Model;

use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\Api\SortOrder;
use Magento\Framework\Exception\NoSuchEntityException;
use VinaiKopp\Kitchen\Api\Data\HamburgerInterface;
use VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface;
use VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterfaceFactory;
use VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface;
use VinaiKopp\Kitchen\Model\ResourceModel\Hamburger\CollectionFactory as HamburgerCollectionFactory;
use VinaiKopp\Kitchen\Model\ResourceModel\Hamburger\Collection;

class HamburgerRepository implements HamburgerRepositoryInterface
{
    /**
     * @var HamburgerFactory
     */
    private $hamburgerFactory;

    /**
     * @var HamburgerCollectionFactory
     */
    private $hamburgerCollectionFactory;

    /**
     * @var HamburgerSearchResultInterfaceFactory
     */
    private $searchResultFactory;

    public function __construct(
        HamburgerFactory $hamburgerFactory,
        HamburgerCollectionFactory $hamburgerCollectionFactory,
        HamburgerSearchResultInterfaceFactory $hamburgerSearchResultInterfaceFactory
    ) {
        $this->hamburgerFactory = $hamburgerFactory;
        $this->hamburgerCollectionFactory = $hamburgerCollectionFactory;
        $this->searchResultFactory = $hamburgerSearchResultInterfaceFactory;
    }

    // ... getById, save and delete methods listed above ...

    public function getList(SearchCriteriaInterface $searchCriteria)
    {
        $collection = $this->collectionFactory->create();

        $this->addFiltersToCollection($searchCriteria, $collection);
        $this->addSortOrdersToCollection($searchCriteria, $collection);
        $this->addPagingToCollection($searchCriteria, $collection);

        $collection->load();

        return $this->buildSearchResult($searchCriteria, $collection);
    }

    private function addFiltersToCollection(SearchCriteriaInterface $searchCriteria, Collection $collection)
    {
        foreach ($searchCriteria->getFilterGroups() as $filterGroup) {
            $fields = $conditions = [];
            foreach ($filterGroup->getFilters() as $filter) {
                $fields[] = $filter->getField();
                $conditions[] = [$filter->getConditionType() => $filter->getValue()];
            }
            $collection->addFieldToFilter($fields, $conditions);
        }
    }

    private function addSortOrdersToCollection(SearchCriteriaInterface $searchCriteria, Collection $collection)
    {
        foreach ((array) $searchCriteria->getSortOrders() as $sortOrder) {
            $direction = $sortOrder->getDirection() == SortOrder::SORT_ASC ? 'asc' : 'desc';
            $collection->addOrder($sortOrder->getField(), $direction);
        }
    }

    private function addPagingToCollection(SearchCriteriaInterface $searchCriteria, Collection $collection)
    {
        $collection->setPageSize($searchCriteria->getPageSize());
        $collection->setCurPage($searchCriteria->getCurrentPage());
    }

    private function buildSearchResult(SearchCriteriaInterface $searchCriteria, Collection $collection)
    {
        $searchResults = $this->searchResultFactory->create();

        $searchResults->setSearchCriteria($searchCriteria);
        $searchResults->setItems($collection->getItems());
        $searchResults->setTotalCount($collection->getSize());

        return $searchResults;
    }
}

एक के भीतर फिल्टर FilterGroupएक का उपयोग कर जोड़ा जा चाहिए या ऑपरेटर।
अलग-अलग फ़िल्टर समूह तार्किक और ऑपरेटर का उपयोग करके संयुक्त होते हैं ।

काजू
यह सबसे बड़ा काम था। अन्य इंटरफ़ेस कार्यान्वयन सरल हैं।

डीटीओ

Magento ने मूल रूप से डेवलपर्स को अलग-अलग वर्गों के रूप में डीटीओ को लागू करने का इरादा किया था, जो इकाई मॉडल से अलग है।

कोर टीम ने केवल ग्राहक मॉड्यूल के लिए ऐसा किया (हालांकि , \Magento\Customer\Api\Data\CustomerInterfaceइसे लागू \Magento\Customer\Model\Data\Customerनहीं किया गया है \Magento\Customer\Model\Customer)।
अन्य सभी मामलों में इकाई मॉडल डीटीओ इंटरफ़ेस को लागू करता है (उदाहरण के लिए \Magento\Catalog\Api\Data\ProductInterfaceद्वारा कार्यान्वित किया जाता है \Magento\Catalog\Model\Product)।

मैंने कोर टीम के सदस्यों से सम्मेलनों में इसके बारे में पूछा है, लेकिन मुझे अच्छी प्रतिक्रिया नहीं मिली कि क्या अच्छा अभ्यास माना जाना है।
मेरी धारणा है कि इस सिफारिश को छोड़ दिया गया है। हालांकि इस पर आधिकारिक बयान प्राप्त करना अच्छा होगा।

अभी के लिए मैंने DTO इंटरफ़ेस कार्यान्वयन के रूप में मॉडल का उपयोग करने के लिए व्यावहारिक निर्णय लिया है। यदि आपको लगता है कि एक अलग डेटा मॉडल का उपयोग करना क्लीनर है, तो ऐसा करने के लिए स्वतंत्र महसूस करें। दोनों दृष्टिकोण अभ्यास में ठीक काम करते हैं।

यदि डीटीओ पूर्णांक विस्तार करता है Magento\Framework\Api\ExtensibleDataInterface, तो मॉडल को विस्तारित करना होगा Magento\Framework\Model\AbstractExtensibleModel
यदि आप एक्स्टेंसिबिलिटी की परवाह नहीं करते हैं, तो मॉडल ओआरएम मॉडल बेस क्लास का विस्तार करना जारी रख सकता है Magento\Framework\Model\AbstractModel

चूंकि उदाहरण HamburgerInterfaceफैली ExtensibleDataInterfaceहैमबर्गर मॉडल का विस्तार AbstractExtensibleModel, के रूप में यहां देखा जा सकता:

<?php

namespace VinaiKopp\Kitchen\Model;

use Magento\Framework\Model\AbstractExtensibleModel;
use VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface;
use VinaiKopp\Kitchen\Api\Data\HamburgerInterface;

class Hamburger extends AbstractExtensibleModel implements HamburgerInterface
{
    const NAME = 'name';
    const INGREDIENTS = 'ingredients';
    const IMAGE_URLS = 'image_urls';

    protected function _construct()
    {
        $this->_init(ResourceModel\Hamburger::class);
    }

    public function getName()
    {
        return $this->_getData(self::NAME);
    }

    public function setName($name)
    {
        $this->setData(self::NAME, $name);
    }

    public function getIngredients()
    {
        return $this->_getData(self::INGREDIENTS);
    }

    public function setIngredients(array $ingredients)
    {
        $this->setData(self::INGREDIENTS, $ingredients);
    }

    public function getImageUrls()
    {
        $this->_getData(self::IMAGE_URLS);
    }

    public function setImageUrls(array $urls)
    {
        $this->setData(self::IMAGE_URLS, $urls);
    }

    public function getExtensionAttributes()
    {
        return $this->_getExtensionAttributes();
    }

    public function setExtensionAttributes(HamburgerExtensionInterface $extensionAttributes)
    {
        $this->_setExtensionAttributes($extensionAttributes);
    }
}

संपत्ति के नाम को स्थिरांक में निकालने से उन्हें एक स्थान पर रखने की अनुमति मिलती है। उन्हें गेट्टर / सेटर जोड़ी द्वारा और डेटाबेस स्क्रिप्ट बनाने वाली सेटअप स्क्रिप्ट द्वारा भी उपयोग किया जा सकता है। अन्यथा उन्हें स्थिरांक में निकालने का कोई लाभ नहीं है।

खोज

यह SearchResultsInterfaceलागू करने के लिए तीन इंटरफेस में से सबसे सरल है, क्योंकि यह एक फ्रेमवर्क क्लास से इसकी सभी कार्यक्षमता को विरासत में दे सकता है।

<?php

namespace VinaiKopp\Kitchen\Model;

use Magento\Framework\Api\SearchResults;
use VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface;

class HamburgerSearchResult extends SearchResults implements HamburgerSearchResultInterface
{

}

ObjectManager वरीयताओं को कॉन्फ़िगर करें

हालांकि कार्यान्वयन पूर्ण हैं, फिर भी हम अन्य वर्गों की निर्भरता के रूप में इंटरफेस का उपयोग नहीं कर सकते हैं, क्योंकि मैगेंटो फ्रेमवर्क ऑब्जेक्ट मैनेजर को यह नहीं पता है कि कार्यान्वयन का क्या उपयोग करना है। हमें etc/di.xmlवरीयताओं के साथ एक कॉन्फ़िगरेशन जोड़ने की आवश्यकता है ।

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" type="VinaiKopp\Kitchen\Model\HamburgerRepository"/>
    <preference for="VinaiKopp\Kitchen\Api\Data\HamburgerInterface" type="VinaiKopp\Kitchen\Model\Hamburger"/>
    <preference for="VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface" type="VinaiKopp\Kitchen\Model\HamburgerSearchResult"/>
</config>

एपीआई संसाधन के रूप में रिपॉजिटरी को कैसे उजागर किया जा सकता है?

यह हिस्सा वास्तव में सरल है, यह इंटरफेस बनाने, कार्यान्वयन और उन्हें एक साथ वायरिंग करने वाले सभी काम से गुजरने का इनाम है।

बस हमें एक etc/webapi.xmlफाइल बनाने की जरूरत है ।

<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    <route method="GET" url="/V1/vinaikopp_hamburgers/:id">
        <service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="getById"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
    <route method="GET" url="/V1/vinaikopp_hamburgers">
        <service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="getList"/>
        <resources>
            <resource ref="anonymouns"/>
        </resources>
    </route>
    <route method="POST" url="/V1/vinaikopp_hamburgers">
        <service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="save"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
    <route method="PUT" url="/V1/vinaikopp_hamburgers">
        <service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="save"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
    <route method="DELETE" url="/V1/vinaikopp_hamburgers">
        <service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="delete"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
</routes>

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

पहला उदाहरण मार्ग में, <route method="GET" url="/V1/vinaikopp_hamburgers/:id">प्लेसहोल्डर :id, मैप की विधि के लिए तर्क के नाम से मेल खाना चाहिए public function getById($id)
दो नामों का मिलान करना है, उदाहरण के लिए /V1/vinaikopp_hamburgers/:hamburgerIdकाम नहीं करेगा, क्योंकि विधि तर्क चर नाम है $id

इस उदाहरण के लिए मैंने पहुँच-योग्यता सेट की है <resource ref="anonymous"/>। इसका मतलब यह है कि संसाधन बिना किसी प्रतिबंध के सार्वजनिक रूप से उजागर होता है!
केवल ग्राहक को लॉग में उपलब्ध संसाधन उपलब्ध कराने के लिए, उपयोग करें <resource ref="self"/>। इस स्थिति meमें संसाधन समापन बिंदु URL में विशेष शब्द का उपयोग $idवर्तमान में ग्राहक में लॉग इन की आईडी के साथ एक तर्क चर को पॉप्युलेट करने के लिए किया जाएगा ।
Magento ग्राहक पर एक नज़र है etc/webapi.xmlऔर CustomerRepositoryInterfaceअगर आप की जरूरत है कि।

अंत में, <resources>किसी व्यवस्थापक उपयोगकर्ता खाते में संसाधन तक पहुंच को प्रतिबंधित करने के लिए भी उपयोग किया जा सकता है। ऐसा करने के लिए <resource>रेफरी को किसी etc/acl.xmlफ़ाइल में परिभाषित पहचानकर्ता के पास सेट करें ।
उदाहरण के लिए, <resource ref="Magento_Customer::manage"/>ग्राहकों को प्रबंधित करने के लिए विशेषाधिकार प्राप्त किसी भी व्यवस्थापक खाते तक पहुंच को प्रतिबंधित करेगा।

कर्ल का उपयोग कर एक उदाहरण एपीआई क्वेरी इस तरह दिख सकती है:

$ curl -X GET http://example.com/rest/V1/vinaikopp_hamburgers/123

नोट: इस के जवाब के रूप में शुरू किया लिखित https://github.com/astorm/pestle/issues/195
की जाँच करें मूसल , खरीदने के Commercebug और एक बन patreon @alanstorm की


1
इस बेहतरीन जवाब के लिए धन्यवाद। क्षमा करें शायद मुझे कुछ याद आ रहा है, लेकिन एक इकाई के लिए एक स्वच्छ इंटरफ़ेस होने का क्या मतलब है जब अंत में इसे AbstractModel से विस्तारित करना होगा जिसमें सेटडेटा विधि है जिसका अर्थ है कि आप इंटरफ़ेस की परवाह किए बिना ऑब्जेक्ट में कुछ भी जोड़ सकते हैं?
एलडीयूसन

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

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

3
मैं क्षमाप्रार्थी हूं। आप जो वर्णन कर रहे हैं, वह सामान्य दृष्टिकोण है। निर्भरता के यांत्रिकी सहज नहीं हैं और चूंकि PHP उन तरीकों की कॉलिंग की अनुमति देता है जो इंटरफ़ेस पर निर्भर होने का हिस्सा नहीं हैं, और यह भी कि इसे संकलित करने की आवश्यकता नहीं है, यह उस तरह से निर्भरता को और अधिक धुंधला और स्पष्ट रूप से देखने के लिए कठिन काम करता है । यह मैगेंटो 2 कोर में भी देखा जा सकता है, जहां कई जगह हैं जहां कार्यान्वयन विधियों को बुलाया जाता है जो इंटरफ़ेस पर निर्भर का हिस्सा नहीं हैं। ये बुरे उदाहरणों के रूप में कार्य करते हैं और स्पष्ट और स्पष्ट समझ पाने के लिए इसे और भी कठिन बनाते हैं।
विनय


35

डिजिटल पियानोवाद पर @ राफेल:

कृपया निम्न नमूना मॉड्यूल संरचना देखें:

app/
   code/
  |    Namespace/
  |   |    Custom/
  |   |   |    Api/
  |   |   |   |    CustomRepositoryInterface.php
  |   |   |   |    Data/
  |   |   |   |   |    CustomInterface.php
  |   |   |   |   |    CustomSearchResultsInterface.php
  |   |   |    etc/
  |   |   |   |    di.xml
  |   |   |   |    module.xml
  |   |   |    Model/
  |   |   |   |    Custom.php
  |   |   |   |    CustomRepository.php
  |   |   |   |    ResourceModel/
  |   |   |   |   |    Custom.php
  1. रिपॉजिटरी इंटरफ़ेस (सेवा अनुबंध) बनाएँ
    Namespace/Custom/Api/CustomRepositoryInterface.php: http://codepad.org/WognSKnH

  2. SearchResultsInterface बनाएं
    Namespace/Custom/Api/Data/CustomSearchResultsInterface.php: http://codepad.org/zcbi8X4Z

  3. कस्टमइंटरफेस (डेटा कंटेनर) बनाएँ
    Namespace/Custom/Api/Data/CustomInterface.php: http://codepad.org/Ze53eT4o

  4. CustomRepository (कंक्रीट रिपोजिटरी) बनाएँ
    Namespace/Custom/Model/CustomRepository.php: http://codepad.org/KNt5QAGZ
    यह वह जगह है जहाँ "जादू" होता है। कंस्ट्रक्टर डि के माध्यम से, आप अपने कस्टम मॉड्यूल के लिए संसाधन मॉडल / संग्रह कारखाने में पास होते हैं; इस रिपॉजिटरी में सहेजें CRUD पद्धति के बारे में, अपने CustomRepositoryInterface के कारण, आपको CustomInterface के एक पैरामीटर में पास होना चाहिए । आपके मॉड्यूल के di.xml में एक इकाई मॉडल के साथ इस प्रकार के इंटरफ़ेस को बदलने के लिए प्राथमिकता है। इकाई मॉडल संसाधन मॉडल में पारित हो जाता है और सहेजा जाता है।

  5. इसमें प्राथमिकता सेट करें
    Namespace/Custom/etc/di.xml: http://codepad.org/KmcoOUeV

  6. कस्टम इंटरफ़ेस (डेटा कंटेनर) को लागू करने वाला इकाई मॉडल
    Namespace/Custom/Model/Custom.php: http://codepad.org/xQiBU7p7

  7. संसाधन मॉडल
    Namespace/Custom/Model/ResourceModel/Custom.php: http://codepad.org/IOsxm9qW

ध्यान देने योग्य कुछ बातें:

  • अस्वीकरण!!! मैंने आपके कस्टम विक्रेता के नाम, एजेंसी का नाम, आदि के स्थान पर "Namespace" का उपयोग किया ... आप अपने मॉड्यूल को एक साथ जोड़ने के लिए जो भी नाम का उपयोग करते हैं ... "Namespace" का वास्तविक उपयोग पूरी तरह से Php में मान्य नहीं है ... तो जानते हैं मैंने सुविधा के लिए ऐसा किया है, और मुझे नहीं लगता कि यह काम करेगा और न ही मैं इसे किसी भी तरह से सुझाव देता हूं।

  • @ रेयान स्ट्रीट ने मुझे यह सिखाया ... इसलिए मैं इसका पूरा श्रेय नहीं लेना चाहता

  • अपनी आवश्यकताओं के अनुरूप रिपोजिटरी के कार्यान्वयन को स्पष्ट रूप से बदलें

  • आप अपने कस्टम इकाई मॉडल / संसाधन मॉडल / ठोस भंडार में संग्रह के साथ सहभागिता को लागू करते हैं ...

  • मुझे पता है कि मैंने आपके प्रश्न में सूचीबद्ध सभी विधियों को संबोधित नहीं किया था, लेकिन यह एक शानदार शुरुआत है और डॉक्स और वास्तविक कार्यान्वयन के बीच अंतर को पाटना चाहिए।


रयान, सेवा अनुबंधों में उल्लिखित तरीके हैं जो किसी भी कस्टम साबुन एपीआई के लिए अनिवार्य हैं जो हम बनाते हैं, अर्थात सहेजें (), हटाएं () आदि?
सुशीवम

क्या आप कृपया मुझे अंदाजा लगा सकते हैं कि magento 2 में कस्टम साबुन एपी कैसे बनाया जाए?
सुशीवम

@ साचिस दुर्भाग्य से, मुझे SOAP के बारे में कोई जानकारी नहीं है। मैंने अभी तक इस पर ध्यान नहीं दिया है और न ही मैंने इसे अभी तक लागू किया है। जो सबसे अच्छा सुझाव मैं दे सकता हूं, वह यह है कि इस संबंध में एक नया प्रश्न खोला जाएगा। मैं कहूंगा कि डॉक्स की जांच करें, लेकिन यह दुख की बात है कि हमेशा कार्रवाई का सबसे अच्छा कोर्स नहीं है (उनकी कमी हो सकती है)। आप हमेशा कोर कोडबेस या 3 पार्टी एक्सटेंशन पर एक नज़र डाल सकते हैं, और देख सकते हैं कि वहां कोई अंतर्दृष्टि है या नहीं। सौभाग्य! यदि आप अपना उत्तर पाते हैं तो यहां लिंक जोड़ना अच्छा हो सकता है। धन्यवाद
ryanF

उत्तर के लिए धन्यवाद @ आर्यन, वैसे भी मैंने अपने मॉड्यूल को REST का उपयोग करके कार्यान्वित किया, क्योंकि इसका प्रकाश SOAP की तुलना में कम था ... अगर मैं SOAP में इसे लागू करता हूं, तो इसे पोस्ट करें
सुशीवम

3
@ryanF इस बहुत उपयोगी उत्तर के लिए धन्यवाद। मुझे पता है कि यह काम करने वाले कोड को कॉपी / पेस्ट करने वाला नहीं है, लेकिन यहां कुछ अन्य लोगों के लाभ के लिए कुछ टाइपोस हैं। रिपॉजिटरी में, CustomSearchResultsInterfaceFactory CustomSearchResultsFactory होना चाहिए। $ searchResults-> setCriteria $ searchResults-> setSearchCriteria होना चाहिए। $ सीमा शुल्क [] फॉर्च्यून में $ सीमा शुल्क [] होना चाहिए। मुझे लगता है कि इसके बारे में है।
tetranz

3

सेवा अनुबंधों का उपयोग करने की पूरी फाइलें

कस्टम / मॉड्यूल / registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Custom_Module',
    __DIR__
);

../etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Custom_Module" setup_version="1.0.0" />
</config>

../Setup/InstallSchema.php

<?php
namespace Custom\Module\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;
class InstallSchema implements InstallSchemaInterface {
    public function install( SchemaSetupInterface $setup, ModuleContextInterface $context ) {
        $installer = $setup;
        $installer->startSetup();
        $table = $installer->getConnection()->newTable(
            $installer->getTable( 'ad_shipping_quote' )
        )->addColumn(
            'entity_id',
            Table::TYPE_SMALLINT,
            null,
            [ 'identity' => true, 'nullable' => false, 'primary' => true ],
            'Post ID'
        )->addColumn(
            'product_id',
            Table::TYPE_SMALLINT,
            255,
            [ ],
            'Post ID'
        )
            ->addColumn(
            'customer_name',
            Table::TYPE_TEXT,
            255,
            [ 'nullable' => false ],
            'Post Title'
        )

            ->addColumn(
            'customer_email',
            Table::TYPE_TEXT,
            '2M',
            [ ],
            'Post Content'
        ) ->addColumn(
                'customer_comments',
                Table::TYPE_TEXT,
                255,
                [ 'nullable' => false ],
                'Post Title'
            )->addColumn(
                'date_added',
                Table::TYPE_TEXT,
                255,
                [ 'nullable' => false ],
                'Post Title'
            )->addColumn(
                'date_updated',
                Table::TYPE_TEXT,
                255,
                [ 'nullable' => false ],
                'Post Title'
            )
            ->setComment(
            'Ad Shipping Quote Table'
        );
        $installer->getConnection()->createTable( $table );
        $installer->endSetup();
    }
}

../etc/di.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Custom\Module\Api\ModelRepositoryInterface"
                type="Custom\Module\Model\ModelRepository" />
    <preference for="Custom\Module\Api\Data\ModelInterface"
                type="Custom\Module\Model\Model" />
    <preference for="Custom\Module\Api\Data\ModelSearchResultsInterface"
                type="Custom\Module\Model\ModelSearchResults" />
</config>

../etc/webapi.xml

  <?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">

    <route method="GET" url="/V1/model/:id">
        <service class="Custom\Module\Api\ModelRepositoryInterface" method="getById"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>


    <route method="GET" url="/V1/model">
        <service class="Custom\Module\Api\ModelRepositoryInterface" method="getList"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
</routes>

../Api/ModelRepositoryInterface.php

  <?php
namespace Custom\Module\Api;

use \Custom\Module\Api\Data\ModelInterface;
use \Magento\Framework\Api\SearchCriteriaInterface;

interface ModelRepositoryInterface
{
    /**
     * @api
     * @param \Custom\Module\Api\Data\ModelInterface $model
     * @return \Custom\Module\Api\Data\ModelInterface
     */
    public function save(ModelInterface $model);

    /**
     * @api
     * @param \Custom\Module\Api\Data\ModelInterface $model
     * @return \Custom\Module\Api\Data\ModelInterface
     */
    public function delete(ModelInterface $model);

    /**
     * @api
     * @param \Custom\Module\Api\Data\ModelInterface $id
     * @return void
     */
    public function deleteById($id);

    /**
     * @api
     * @param int $id
     * @return \Custom\Module\Api\Data\ModelInterface
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function getById($id);

    /**
     * @api
     * @param \Magento\Framework\Api\SearchCriteriaInterface $criteria
     * @return \Custom\Module\Api\Data\ModelSearchResultsInterface
     */
    public function getList(SearchCriteriaInterface $criteria);
}

../Api/Data/ModelInterface.php

<?php
namespace Custom\Module\Api\Data;

interface ModelInterface
{
    /**
     * Return the Entity ID
     *
     * @return int
     */
    public function getEntityId();

    /**
     * Set Entity ID
     *
     * @param int $id
     * @return $this
     */
    public function setEntityId($id);

    /**
     * Return the Product ID associated with Quote
     *
     * @return int
     */
    public function getProductId();

    /**
     * Set the Product ID associated with Quote
     *
     * @param int $productId
     * @return $this
     */
    public function setProductId($productId);

    /**
     * Return the Customer Name
     *
     * @return string
     */
    public function getCustomerName();

    /**
     * Set the Customer Name
     *
     * @param string $customerName
     * @return $this
     */
    public function setCustomerName($customerName);

    /**
     * Return the Customer Email
     *
     * @return string
     */
    public function getCustomerEmail();

    /**
     * Set the Customer Email
     *
     * @param string $customerEmail
     * @return $this
     */
    public function setCustomerEmail($customerEmail);

    /**
     * Return the Customer Comments
     *
     * @return string
     */
    public function getCustomerComments();

    /**
     * Set the Customer Comments
     *
     * @param string $customerComments
     * @return $this
     */
    public function setCustomerComments($customerComments);

    /**
     * Return the Date and Time of record added
     *
     * @return string
     */
    public function getDateAdded();

    /**
     * Set the Date and Time of record added
     *
     * @param string $date
     * @return $this
     */
    public function setDateAdded($date);

    /**
     * Return the Date and Time of record updated
     *
     * @return string
     */
    public function getDateUpdated();

    /**
     * Set the Date and Time of record updated
     *
     * @param string $date
     * @return $this
     */
    public function setDateUpdated($date);
}

..Api / डेटा / ModelSearchResultsInterface.php

<?php

namespace Custom\Module\Api\Data;

use Magento\Framework\Api\SearchResultsInterface;

interface ModelSearchResultsInterface extends SearchResultsInterface
{
    /**
     * @return \Custom\Module\Api\Data\ModelInterface[]
     */
    public function getItems();

    /**
     * @param \Custom\Module\Api\Data\ModelInterface[] $items
     * @return $this
     */
    public function setItems(array $items);
}

../Model/Model.php

    <?php

namespace Custom\Module\Model;

use Custom\Module\Api\Data\ModelInterface;

class Model extends \Magento\Framework\Model\AbstractModel implements
    \Custom\Module\Api\Data\ModelInterface
{
    protected function _construct()
    {
        $this->_init('Custom\Module\Model\ResourceModel\Model');
    }

    /**
     * @inheritdoc
     */
    public function getEntityId()
    {
        return $this->_getData('entity_id');
    }

    /**
     * @inheritdoc
     */
    public function setEntityId($id)
    {
        $this->setData('entity_id', $id);
    }

    /**
     * @inheritdoc
     */
    public function getProductId()
    {
        return $this->_getData('product_id');
    }

    /**
     * @inheritdoc
     */
    public function setProductId($productId)
    {
        $this->setData('product_id', $productId);
    }

    /**
     * @inheritdoc
     */
    public function getCustomerName()
    {
        return $this->_getData('customer_name');
    }

    /**
     * @inheritdoc
     */
    public function setCustomerName($customerName)
    {
        $this->setData('customer_name', $customerName);
    }

    /**
     * @inheritdoc
     */
    public function getCustomerEmail()
    {
        return $this->_getData('customer_email');
    }

    /**
     * @inheritdoc
     */
    public function setCustomerEmail($customerEmail)
    {
        $this->setData('customer_email', $customerEmail);
    }

    /**
     * @inheritdoc
     */
    public function getCustomerComments()
    {
        return $this->_getData('customer_comments');
    }

    /**
     * @inheritdoc
     */
    public function setCustomerComments($customerComments)
    {
        $this->setData('customer_comments', $customerComments);
    }

    /**
     * @inheritdoc
     */
    public function getDateAdded()
    {
        return $this->_getData('date_added');
    }

    /**
     * @inheritdoc
     */
    public function setDateAdded($date)
    {
        $this->setData('date_added', $date);
    }

    /**
     * @inheritdoc
     */
    public function getDateUpdated()
    {
        return $this->_getData('date_updated');
    }

    /**
     * @inheritdoc
     */
    public function setDateUpdated($date)
    {
        $this->setData('date_updated', $date);
    }
}

../Model/ResourceModel/Model.php

<?php

namespace Custom\Module\Model\ResourceModel;

class Model extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    protected $_idFieldName = 'entity_id';

    protected function _construct()
    {
        $this->_init('ad_shipping_quote','entity_id');
    }
}

../Model/ResourceModel/Model/Collection.php

<?php

namespace Custom\Module\Model\ResourceModel\Model;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    protected $_idFieldName = 'entity_id';
    protected $_eventPrefix = 'ad_shipping_quote_collection';
    protected $_eventObject = 'quote_collection';

    protected function _construct()
    {
        $this->_init('Custom\Module\Model\Model', 'Custom\Module\Model\ResourceModel\Model');
    }
}

../Model/ModelRepository.php

 <?php
    namespace Custom\Module\Model;

    use \Custom\Module\Api\Data\ModelInterface;
    use \Custom\Module\Model\ResourceModel\Model as ObjectResourceModel;
    use \Magento\Framework\Api\SearchCriteriaInterface;
    use \Magento\Framework\Exception\CouldNotSaveException;
    use \Magento\Framework\Exception\NoSuchEntityException;
    use \Magento\Framework\Exception\CouldNotDeleteException;

    class ModelRepository implements \Custom\Module\Api\ModelRepositoryInterface
    {
        protected $objectFactory;

        protected $objectResourceModel;

        protected $collectionFactory;

        protected $searchResultsFactory;

        public function __construct(
            \Custom\Module\Model\ModelFactory $objectFactory,
            ObjectResourceModel $objectResourceModel,
            \Custom\Module\Model\ResourceModel\Model\CollectionFactory $collectionFactory,
            \Magento\Framework\Api\SearchResultsInterfaceFactory $searchResultsFactory
        ) {
            $this->objectFactory        = $objectFactory;
            $this->objectResourceModel  = $objectResourceModel;
            $this->collectionFactory    = $collectionFactory;
            $this->searchResultsFactory = $searchResultsFactory;
        }

        public function save(ModelInterface $object)
        {
            $name = $object->getCustomerName();
            $hasSpouse = $object->getSpouse();
            if ($hasSpouse == true) {
                $name = "Mrs. " . $name;
            } else {
                $name = "Miss. " . $name;
            }
            $object->setCustomerName($name);
            try {
                $this->objectResourceModel->save($object);
            } catch (\Exception $e) {
                throw new CouldNotSaveException(__($e->getMessage()));
            }
            return $object;
        }

        /**
         * @inheritdoc
         */
        public function getById($id)
        {
            $object = $this->objectFactory->create();
            $this->objectResourceModel->load($object, $id);
            if (!$object->getId()) {
                throw new NoSuchEntityException(__('Object with id "%1" does not exist.', $id));
            }
            return $object;
        }

        public function delete(ModelInterface $object)
        {
            try {
                $this->objectResourceModel->delete($object);
            } catch (\Exception $exception) {
                throw new CouldNotDeleteException(__($exception->getMessage()));
            }
            return true;
        }

        public function deleteById($id)
        {
            return $this->delete($this->getById($id));
        }

        /**
         * @inheritdoc
         */
        public function getList(SearchCriteriaInterface $criteria)
        {
            $searchResults = $this->searchResultsFactory->create();
            $searchResults->setSearchCriteria($criteria);
            $collection = $this->collectionFactory->create();
            foreach ($criteria->getFilterGroups() as $filterGroup) {
                $fields = [];
                $conditions = [];
                foreach ($filterGroup->getFilters() as $filter) {
                    $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq';
                    $fields[] = $filter->getField();
                    $conditions[] = [$condition => $filter->getValue()];
                }
                if ($fields) {
                    $collection->addFieldToFilter($fields, $conditions);
                }
            }
            $searchResults->setTotalCount($collection->getSize());
            $sortOrders = $criteria->getSortOrders();
            if ($sortOrders) {
                /** @var SortOrder $sortOrder */
                foreach ($sortOrders as $sortOrder) {
                    $collection->addOrder(
                        $sortOrder->getField(),
                        ($sortOrder->getDirection() == SortOrder::SORT_ASC) ? 'ASC' : 'DESC'
                    );
                }
            }
            $collection->setCurPage($criteria->getCurrentPage());
            $collection->setPageSize($criteria->getPageSize());
            $objects = [];
            foreach ($collection as $objectModel) {
                $objects[] = $objectModel;
            }
            $searchResults->setItems($objects);
            return $searchResults;
        }
    }

../Model/ModelSearchResults.php

namespace Custom\Module\Model;

use \Magento\Framework\Api\SearchResults;
use \Custom\Module\Api\Data\ModelSearchResultsInterface;


class ModelSearchResults extends SearchResults implements ModelSearchResultsInterface
{

}

../Controller/Index/Save.php

<?php

namespace Custom\Module\Controller\Index;

use \Magento\Framework\Controller\Result\RawFactory;

class Save extends \Magento\Framework\App\Action\Action
{

    /**
     * Index resultPageFactory
     * @var PageFactory
     */
    private $resultPageFactory;
    /**
     * @var
     */
    private $modelFactory;
    /**
     * @var
     */
    private $modelRepository;


    /**
     * Index constructor.
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Custom\Module\Model\ModelFactory $modelFactory
     * @param \Custom\Module\Model\ModelRepository $modelRepository
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Custom\Module\Model\ModelFactory $modelFactory,
        \Custom\Module\Model\ModelRepository $modelRepository
) {
        $this->resultPageFactory = $resultPageFactory;
        $this->modelFactory = $modelFactory;
        $this->modelRepository = $modelRepository;
        return parent::__construct($context);


    }

    /**
     * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $data = [

            "product_id" => 201,
            "customer_name" => "Katrina",
            "customer_email" => "karina@kapoor.com",
            "spouse" => 1
        ];

        $obj = $this->modelFactory->create();
        $this->modelRepository->save($obj->addData($data)); // Service Contract


        //$obj->addData($data)->save(); // Model / Resource Model

        $this->resultFactory->create("raw");
    }
}

../Controller/Index/Getlist.php

<?php

namespace Custom\Module\Controller\Index;

use \Magento\Framework\Controller\Result\RawFactory;

class Getlist extends \Magento\Framework\App\Action\Action
{

    /**
     * Index resultPageFactory
     * @var PageFactory
     */
    private $resultPageFactory;
    /**
     * @var
     */
    private $modelFactory;
    /**
     * @var
     */
    private $modelRepository;
    /**
     * @var
     */
    private $searchCriteriaBuilder;


    /**
     * Index constructor.
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Custom\Module\Model\ModelRepository $modelRepository
     * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Custom\Module\Model\ModelRepository $modelRepository,
        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
) {
        $this->resultPageFactory = $resultPageFactory;
        $this->modelRepository = $modelRepository;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
        return parent::__construct($context);
    }

    /**
     * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $_filter = $this->searchCriteriaBuilder
            ->addFilter("customer_name", "%na%", "like")->create();
        $list = $this->modelRepository->getList($_filter);
        $results = $list->getItems();
        foreach ($results as $result) {
            echo $result->getCustomerName() . "<br>";
        }




        $this->resultFactory->create("raw");
    }
}

../Controller/Index/Getbyid.php

<?php

namespace Custom\Module\Controller\Index;

use \Magento\Framework\Controller\Result\RawFactory;

class Getbyid extends \Magento\Framework\App\Action\Action
{

    /**
     * Index resultPageFactory
     * @var PageFactory
     */
    private $resultPageFactory;
    /**
     * @var
     */
    private $modelRepository;

    /**
     * Index constructor.
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Custom\Module\Model\ModelRepository $modelRepository
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Custom\Module\Model\ModelRepository $modelRepository

) {
        $this->resultPageFactory = $resultPageFactory;
        $this->modelRepository = $modelRepository;
        return parent::__construct($context);
    }

    public function execute()
    {

        $search = $this->modelRepository->getById(1);
        print_r($search->getData());

        $this->resultFactory->create("raw");
    }
}

../Controller/Index/Deletebyid.php

<?php

namespace Custom\Module\Controller\Index;

use \Magento\Framework\Controller\Result\RawFactory;

class Deletbyid extends \Magento\Framework\App\Action\Action
{

    /**
     * Index resultPageFactory
     * @var PageFactory
     */
    private $resultPageFactory;
    /**
     * @var
     */
    private $modelRepository;

    /**
     * Index constructor.
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Custom\Module\Model\ModelRepository $modelRepository
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Custom\Module\Model\ModelRepository $modelRepository

) {
        $this->resultPageFactory = $resultPageFactory;
        $this->modelRepository = $modelRepository;
        return parent::__construct($context);
    }

    public function execute()
    {

        $this->modelRepository->deleteById(1);

        $this->resultFactory->create("raw");
    }
}

../Controller/Index/Del.php

<?php

namespace Custom\Module\Controller\Index;

use \Magento\Framework\Controller\Result\RawFactory;

class Del extends \Magento\Framework\App\Action\Action
{

    /**
     * Index resultPageFactory
     * @var PageFactory
     */
    private $resultPageFactory;
    /**
     * @var
     */
    private $modelRepository;

    /**
     * Index constructor.
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Custom\Module\Model\ModelFactory $modelFactory
     * @param \Custom\Module\Model\ModelRepository $modelRepository
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Custom\Module\Model\ModelFactory $modelFactory,
        \Custom\Module\Model\ModelRepository $modelRepository

) {
        $this->resultPageFactory = $resultPageFactory;
        $this->modelFactory = $modelFactory;
        $this->modelRepository = $modelRepository;
        return parent::__construct($context);
    }

    public function execute()
    {
        $obj = $this->modelFactory->create()->load(2);
         $this->modelRepository->delete($obj);

        $this->resultFactory->create("raw");
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.