Magento 2'de özel bir modül için servis sözleşmesi nasıl uygulanır?


42

Bu yayına görüldüğü gibi: Kaldırılmış kaydedip Özet Modeli yük yöntemlerisave ve loadyöntemlerin Magento 2 kaldırılıyor dalı gelişir.

Bu nedenle, şimdi iyi uygulama şu anda CRUD kurumlarıyla başa çıkmak için hizmet sözleşmeleri yapmaktır.

Özel modül varlıklarım için hizmet sözleşmelerini uygulamak için izlemem gereken adım adım işlem nedir?

Not: CRUD modellerimde binlerce yöntem olabileceğini biliyorum, sadece burada belirtildiği gibi açık yöntemleri istiyorum: http://devdocs.magento.com/guides/v2.0/extension-dev-guide /service-contracts/design-patterns.html :

  • get
  • save
  • getList
  • delete
  • deleteById

Yanıtlar:


89

@RyanF'ın mükemmel cevabına ek olarak biraz daha ayrıntılı bilgi vermek istiyorum.

Özel varlıklar için bir depo ekleme nedenlerini özetlemek, bunun nasıl yapılacağına örnekler vermek ve ayrıca bu depo yöntemlerinin Web API'sinin bir parçası olarak nasıl gösterileceğini açıklamak istiyorum.

Feragatname: Yalnızca üçüncü parti modüller için bunun nasıl yapılacağı ile ilgili pratik bir yaklaşımı tarif ediyorum - çekirdek ekiplerin takip ettikleri (ya da değil) kendi standartları var.

Genel olarak, bir deponun amacı, depolamaya ilişkin mantığı gizlemektir.
Bir deponun müşterisi, geri gönderilen varlığın bir dizide bellekte tutulması, bir MySQL veritabanından alınması, uzak bir API'den veya bir dosyadan getirilmesi ile ilgilenmemelidir.
Magento'nun çekirdek ekibinin bunu yaptığını ve gelecekte ORM'yi değiştirebileceklerini veya değiştirebileceklerini farz ediyorum. Magento'da ORM şu anda Modeller, Kaynak Modelleri ve Koleksiyonlardan oluşmaktadır.
Üçüncü taraf bir modül yalnızca depoları kullanırsa, Magento verilerin nasıl ve nerede depolandığını değiştirebilir ve bu derin değişikliklere rağmen modül çalışmaya devam eder.

Depoları genellikle gibi yöntemleri var findById(), findByName(), put()veya remove().
Magento Bu sık denir getbyId(), save()ve delete()hatta onlar başka bir şey yapıyor ama CRUD DB işlemleri vardır davranarak,.

Magento 2 depo yöntemleri kolayca API kaynakları olarak gösterilebilir, böylece onları üçüncü parti sistemler veya başsız Magento örnekleri ile entegrasyon için değerli kılar.

"Özel varlığım için bir depo eklemeli miyim?"

Her zamanki gibi, cevap

"Değişir".

Uzun lafın kısası, eğer varlıklarınız diğer modüller tarafından kullanılacaksa, o zaman evet, muhtemelen bir depo eklemek istersiniz.

Burada sayılan başka bir faktör daha var: Magento 2'de, depolar kolayca Web API'sı (REST ve SOAP - kaynakları) olarak gösterilebilir.

Eğer üçüncü parti sistem entegrasyonları veya başsız bir Magento kurulumundan dolayı bu sizin için ilginçse, o zaman tekrar, evet, muhtemelen varlığınız için bir depo eklemek istersiniz.

Özel varlığım için nasıl bir havuz eklerim?

Varlığınızı REST API’nin bir parçası olarak göstermek istediğinizi varsayalım. Eğer bu doğru değilse, arayüzleri oluşturma konusundaki yaklaşan kısmı atlayabilir ve aşağıdaki "Depo ve veri modeli uygulamasını oluştur" seçeneğine doğrudan gidebilirsiniz.

Havuz ve veri modeli arayüzleri oluşturun

Api/Data/Modülünüzdeki klasörleri oluşturun . Bu sadece kongredir, farklı bir konum kullanabilirsiniz, ancak kullanmamalısınız.
Depo Api/klasöre gider . Alt Data/dizin daha sonra içindir.

Içinde Api/, göstermek istediğiniz yöntemlerle bir PHP arayüzü oluşturun. Magento 2 konvansiyonlarına göre, tüm arayüz isimleri sonek ile biter Interface.
Mesela bir Hamburgervarlık için arayüzü yaratacağım Api/HamburgerRepositoryInterface.

Havuz arayüzü oluştur

Magento 2 depoları bir modülün etki alanı mantığının bir parçasıdır. Bu, bir havuzun uygulaması gereken sabit bir yöntem seti olmadığı anlamına gelir.
Tamamen modülün amacına bağlıdır.

Bununla birlikte, pratikte tüm depolar oldukça benzerdir. CRUD işlevselliği için sarmalayıcılar.
Çoğu yöntemleri var getById, save, deleteve getList.
Dahası, örneğin bir müşteriyi e-posta yoluyla alan ve böylece bir müşteriyi işletme kimliği ile almak için kullanılan CustomerRepositorybir yöntem vardır . getgetById

Bir hamburger işletmesi için örnek bir depo arayüzü:

<?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);

}

Önemli! İşte timesinks ol!
Burada yanlış yaparsanız hata ayıklamak zor olan birkaç getcha var:

  1. DO NOT kullanmak PHP7 REST API içine bu kanca istiyorsanız sayıl argüman türlerini veya dönüş türleri!
  2. Tüm değişkenlere PHPDoc ek açıklamaları ve tüm yöntemlere dönüş türlerini ekleyin!
  3. PHPDoc bloğunda Tam Nitelikli Sınıf Adları kullanın !

Açıklamalar, verilerin JSON veya XML'den nasıl dönüştürüleceğini belirlemek için Magento Çerçevesi tarafından ayrıştırılır. Sınıf ithalatı (yani useifadeler) uygulanmaz!

Her yöntemin, herhangi bir argüman tipine ve dönüş tipine sahip bir ek açıklaması olmalıdır. Bir yöntem argüman almasa ve hiçbir şey döndürmezse bile, ek açıklamaya sahip olması gerekir:

/**
 * @return void
 */

Sayısal tiplerin ( string, int, floatve bool) de bağımsız değişkenler için ve bir geri dönüş değeri olarak, her ikisi de belirtilmelidir gerekir.

Yukarıdaki örnekte, nesneleri döndüren yöntemlere ilişkin ek açıklamaların da arabirimler olarak belirtildiğini unutmayın.
Dönüş tipi arabirimlerinin tümü Api\Dataisim / dizin içindedir.
Bu, herhangi bir iş mantığı içermediklerini belirtmek içindir. Onlar sadece veri torbasıdır.
Daha sonra bu arayüzleri oluşturmalıyız.

DTO arayüzü oluşturun

Bence Magento, bu arayüzleri "veri modelleri" olarak adlandırıyor, hiç sevmediğim bir isim.
Bu sınıf türü genellikle Veri Aktarım Nesnesi veya DTO olarak bilinir .
Bu DTO sınıfları sadece tüm özellikleri için alıcılara ve ayarlayıcılara sahiptir.

DTO'yu veri modeli üzerinden kullanmayı tercih etmemin nedeni, ORM veri modelleri, kaynak modelleri veya görünüm modelleri ile karıştırılmasının daha az kolay olması ... zaten çok fazla şey Magento'da bulunan modellerdir.

Depolara uygulanan PHP7 tipleme ile ilgili aynı kısıtlamalar DTO'lar için de geçerlidir.
Ayrıca, her yöntemin, tüm argüman tiplerine ve dönüş tipine bir ek açıklaması olması gerekir.

<?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);
}

Bir yöntem bir diziyi alır veya döndürürse, dizideki öğelerin türünün PHPDoc ek açıklamasında ve ardından bir açılış ve kapanış köşeli parantez içinde belirtilmesi gerekir [].
Bu, hem skaler değerler (örneğin int[]) hem de nesneler (örneğin IngredientInterface[]) için geçerlidir.

Api\Data\IngredientInterfaceBir nesne dizisi döndüren bir yöntem için bir örnek olarak kullandığımı , bileşenlerin kodunu bu yazıya zorlamayacağım.

ExtensibleDataInterface?

Yukarıdaki örnekte, HamburgerInterfaceuzanır ExtensibleDataInterface.
Teknik olarak, bu yalnızca, diğer modüllerin varlığınıza özellikler ekleyebilmesini istiyorsanız gereklidir.
Öyleyse, getExtensionAttributes()ve adında kongre ile başka bir alıcı / ayarlayıcı çifti eklemeniz gerekir setExtensionAttributes().

Bu yöntemin dönüş türünün isimlendirilmesi çok önemlidir!

Magento 2 çerçevesi, haklı olarak isimlendirirseniz, uygulama için arayüzü, uygulamayı ve fabrikayı üretecektir. Bu mekaniğin detayları bu yazının kapsamı dışında.
Sadece, genişletilebilir yapmak istediğiniz nesnenin arayüzü çağrılırsa \VinaiKopp\Kitchen\Api\Data\HamburgerInterface, extension niteliğinin type olması gerekir \VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface. Bu yüzden, kelimenin Extensionismin Interfacesonundan hemen önce eklenmesi gerekir.

Varlığınızın genişletilebilir olmasını istemiyorsanız, DTO arayüzü başka herhangi bir arayüzü genişletmek zorunda değildir ve getExtensionAttributes()ve setExtensionAttributes()yöntemleri atlanabilir.

Şimdilik DTO arayüzü hakkında yeterli, depo arayüzüne geri dönme zamanı.

GetList () dönüş türü SearchResults

Havuz yöntemi getList, başka bir tür, yani bir SearchResultsInterfaceörnek döndürür .

Metot getListelbette sadece belirtilenlerle eşleşen bir nesne dizisi döndürür SearchCriteria, ancak bir SearchResultsörnek döndürmek döndürülen değerlere bazı yararlı meta veriler eklenmesini sağlar.

Bunun depo getList()yöntemi uygulamasında aşağıda nasıl çalıştığını görebilirsiniz .

Örnek hamburger arama sonucu arayüzü:

<?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);
}

Tüm bu arabirim, iki yöntem getItems()ve setItems()ana arabirimin türlerini geçersiz kılar .

Arayüzlerin özeti

Şimdi aşağıdaki arayüzlere sahibiz:

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

Depo, hiçbir şey uzanır uzanır , ve genişletir .
HamburgerInterface\Magento\Framework\Api\ExtensibleDataInterface
HamburgerSearchResultInterface\Magento\Framework\Api\SearchResultsInterface

Havuz ve veri modeli uygulamaları oluşturma

Bir sonraki adım, üç arayüzün uygulamalarını oluşturmaktır.

Havuz

Temelde, depo ORM'yi işini yapmak için kullanır.

getById(), save() Ve delete()yöntemler oldukça yalındır vardır. Aşağıda daha biraz görülebileceği gibi, bir yapıcı bağımsız değişken olarak depo içine enjekte edilir.
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);
}

Şimdi bir havuzun en ilginç kısmı, getList()yöntem. Yöntem çevirmek zorundadır koleksiyonu yöntem çağrıları içine koşulları.
getList()SerachCriteria

İşin en zor yanı , özellikle toplama koşullarını ayarlama sözdizimi, bir EAV veya düz bir masa varlığı olup olmadığına bağlı olarak farklı olduğundan, filtreler için doğru koşulları ANDve ORkoşulları sağlamaktır.

Çoğu durumda, getList()aşağıdaki örnekte gösterildiği gibi uygulanabilir.

<?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;
    }
}

Bir içindeki filtreler FilterGroupbir OR operatörü kullanılarak birleştirilmelidir .
Ayrı filtre grupları, mantıksal AND operatörü kullanılarak birleştirilir .

Phew
Bu en büyük işti. Diğer arayüz uygulamaları daha basittir.

DTO

Magento ilk olarak, geliştiricileri DTO'yu varlık modelinden farklı olarak ayrı sınıflar olarak uygulama niyetindeydi.

Çekirdek takımı sadece olsa müşteri modülü (için yaptım \Magento\Customer\Api\Data\CustomerInterfacetarafından uygulanmaktadır \Magento\Customer\Model\Data\Customerdeğil \Magento\Customer\Model\Customer).
Diğer tüm durumlarda varlık modeli DTO arayüzünü uygular (örneğin \Magento\Catalog\Api\Data\ProductInterfacetarafından uygulanır \Magento\Catalog\Model\Product).

Konferanstaki çekirdek ekibin üyelerine bu konuyu sordum, ancak iyi uygulama olarak kabul edilmesi gereken net bir yanıt alamadım.
Benim izlenimim bu tavsiyenin terk edilmiş olduğudur. Bu konuda resmi bir açıklama almak iyi olurdu.

Şimdilik, modeli DTO arayüz uygulaması olarak kullanmak için pratik bir karar verdim. Ayrı bir veri modeli kullanmanın daha temiz olduğunu düşünüyorsanız, bunu yapmaktan çekinmeyin. Her iki yaklaşım da pratikte iyi çalışır.

DTO etkileşimi uzatırsa Magento\Framework\Api\ExtensibleDataInterface, modelin uzatılması gerekir Magento\Framework\Model\AbstractExtensibleModel.
Genişletilebilirliği umursamıyorsanız, model ORM model temel sınıfını genişletmeye devam edebilir Magento\Framework\Model\AbstractModel.

Örnek HamburgerInterfacegenişlediğinden, ExtensibleDataInterfacehamburger modeli AbstractExtensibleModelburada görüldüğü gibi, genişler :

<?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);
    }
}

Özellik adlarını sabitlere ayıklamak, onları bir yerde tutmaya izin verir. Alıcı / ayarlayıcı çifti tarafından ve ayrıca veritabanı tablosunu oluşturan Setup komut dosyası tarafından kullanılabilirler. Aksi halde, bunları sabitlere çıkarmakta fayda yoktur.

SearchResult

Bu SearchResultsInterface, uygulanacak üç arayüzün en basitidir, çünkü bütün işlevselliklerini bir çerçeve sınıfından miras alabilir.

<?php

namespace VinaiKopp\Kitchen\Model;

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

class HamburgerSearchResult extends SearchResults implements HamburgerSearchResultInterface
{

}

ObjectManager tercihlerini yapılandırma

Uygulamalar tamamlanmasına rağmen, Magento Framework nesne yöneticisi hangi uygulamaları kullanacağını bilmediğinden arayüzleri diğer sınıfların bağımlılıkları olarak kullanamıyoruz. etc/di.xmlTercihler için bir konfigürasyon eklememiz gerekiyor .

<?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>

Depo bir API kaynağı olarak nasıl gösterilebilir?

Bu kısım gerçekten basittir, ara yüzleri oluşturan tüm çalışmalardan, uygulamalardan ve onları birbirine bağlayanlardan geçmenin ödülü.

Tek yapmamız gereken bir etc/webapi.xmldosya oluşturmak .

<?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>

Bu konfigürasyonun yalnızca deponun REST bitiş noktaları olarak kullanılmasına izin vermediğini, aynı zamanda SOAP API'sinin bir parçası olarak yöntemleri de ortaya koyduğunu unutmayın.

İlk örnek rotada, <route method="GET" url="/V1/vinaikopp_hamburgers/:id">yer tutucu :id, argümanın adını eşlenen yöntemle eşleştirmek zorundadır public function getById($id).
İki /V1/vinaikopp_hamburgers/:hamburgerIdargüman eşleşmelidir, örneğin , metot argümanı değişken ismi olduğu için işe yaramaz $id.

Bu örnek için erişilebilirliği ayarlıyorum <resource ref="anonymous"/>. Bu, kaynağın herhangi bir kısıtlama olmaksızın kamuya açık olarak kullanıldığı anlamına gelir!
Bir kaynağı yalnızca giriş yapmış bir müşterinin kullanımına açmak için kullanın <resource ref="self"/>. Bu durumda, mekaynak bitiş noktası URL'sindeki özel kelime $id, şu anda oturum açmış olan müşterinin kimliğiyle bir değişken değişkenini doldurmak için kullanılacaktır .
Magento Müşterisine bir göz atın etc/webapi.xmlve CustomerRepositoryInterfaceihtiyacınız olursa.

Son olarak, <resources>bir kaynağa yönetici kullanıcı hesabına erişimi kısıtlamak için de kullanılabilir. Bunu yapmak için <resource>ref'ı bir etc/acl.xmldosyada tanımlanan bir tanımlayıcıya ayarlayın .
Örneğin, <resource ref="Magento_Customer::manage"/>müşterileri yönetmek için ayrıcalıklı olan herhangi bir yönetici hesabına erişimi kısıtlar.

Curl kullanarak örnek bir API sorgusu şöyle görünebilir:

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

Not: Bu bir cevap olarak başladı yazılı https://github.com/astorm/pestle/issues/195
göz atın Havaneli , satın Commercebug ve haline patreon @alanstorm arasında


1
Bu harika cevap için teşekkürler. Üzgünüm belki de bir şeyleri özlüyorum, ama sonunda bir varlık için temiz bir arayüze sahip olmanın amacı nedir?
LDusan

Bir sınıf herhangi bir sayıda arayüzü uygulayabilir ve ayrıca ek yöntemler de ekleyebilir. Önemli olan, herhangi bir sınıfın sadece arayüz yöntemlerine dayanması ve bu nedenle diğerlerini bilmemesidir. Bu, harici sınıfları bozmadan herhangi bir zamanda değiştirilebilen arayüz dışı yöntem uygulama detaylarını yapar. Bağımlılık inversiyonunun arkasındaki fikir budur. Hem sınıf hem de herhangi bir müşteri arayüze bağlı ve uygulama detaylarını bilmiyor. Bu açıklığa kavuşturuyor mu?
Vinai

Cevabınız için teşekkürler, ne demek istediğinizi anlıyorum. Mesele şu ki, setData genel bir yöntemdir, bu yüzden uygulama detayı olarak değerlendirilip değerlendirilemeyeceğinden emin değilim. Genel yöntem gibi kullanılması gerekiyorsa, değiştirildiği zaman harici hiçbir şeyi kırmayacağından nasıl emin olabiliriz?
LDusan

3
Özür dilerim. Tarif ettiğiniz şey ortak bir bakış açısıdır. Bağımlılık mekaniği sezgisel değildir ve PHP, arayüze bağlı olmayan yöntemlerin çağrılmasına izin verdiğinden ve ayrıca derlenmesi gerekmediğinden, bağımlılıkların daha bulanık ve net görünmesini zorlaştırır. . Bu, Magento 2 çekirdeğinde de görülebilir, burada uygulama yöntemlerinin ara yüze bağımlı olmayan birçok yerde kullanıldığı yerler vardır. Bunlar kötü örnekler olarak hizmet etmekte ve net ve sağlam bir anlayışa sahip olmayı daha da zorlaştırmaktadır.
Vinai


35

Digital Pianism şirketinde @Raphael:

Lütfen aşağıdaki örnek modül yapısına bakınız:

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. Havuz arayüzü oluşturma (Servis Sözleşmesi)
    Namespace/Custom/Api/CustomRepositoryInterface.php: http://codepad.org/WognSKnH

  2. SearchResultsInterface oluşturun
    Namespace/Custom/Api/Data/CustomSearchResultsInterface.php: http://codepad.org/zcbi8X4Z

  3. CustomInterface (Veri Konteyneri) Yaratın
    Namespace/Custom/Api/Data/CustomInterface.php: http://codepad.org/Ze53eT4o

  4. CustomRepository (Beton Havuzu) Yaratın
    Namespace/Custom/Model/CustomRepository.php: http://codepad.org/KNt5QAGZ
    Bu, "sihir" in gerçekleştiği yerdir. Yapıcı DI aracılığıyla, özel modülünüz için kaynak model / toplama fabrikasına geçersiniz; Nedeniyle CustomRepositoryInterface için, bu depodaki CRUD kaydetme yöntemi ile ilgili olarak, sen gerekir CustomInterface bir parametrede geçmektedir. Modülünüzün di.xml bu tip bir arayüzü bir varlık modeliyle değiştirme tercihine sahiptir. Varlık modeli Kaynak Modeline geçer ve kaydedilir.

  5. Tercihi şu şekilde ayarlayın
    Namespace/Custom/etc/di.xml: http://codepad.org/KmcoOUeV

  6. Özel Arabirim (Veri Kabı) uygulayan varlık modeli
    Namespace/Custom/Model/Custom.php: http://codepad.org/xQiBU7p7 .

  7. Kaynak modeli
    Namespace/Custom/Model/ResourceModel/Custom.php: http://codepad.org/IOsxm9qW

Unutulmaması gereken birkaç şey:

  • Yasal Uyarı !!! Özel satıcı adınız, acente adınız, vb. Yerine "Namespace" i kullandım. Modüllerinizi bir arada gruplamak için ne kullanırsanız kullanın ... "Namespace" in gerçek kullanımı tamamen Php'da geçerli değildir ... Ben kolaylık uğruna bu yaptığını ve ben emin değil düşünüyorum bu çalışacaktır, ne de herhangi bir şekilde bunu önermek yapmak.

  • @Ryan Street bana bunu öğretti ... bu yüzden tüm krediyi almak istemiyorum

  • İhtiyaçlarınıza uyacak şekilde Deponun uygulamasını açıkça değiştirin

  • Özel depo modelleri / kaynak modelleri / koleksiyonlarınızla etkileşimi somut depoda uygularsınız ...

  • Sorunuzda listelediğiniz tüm yöntemleri ele almadığımı biliyorum, ancak bu harika bir başlangıç ​​ve dokümanlar ile gerçek uygulama arasındaki boşluğu kapatması gerekiyor.


Ryan, Hizmet Sözleşmelerinde belirtilen yöntemler oluşturduğumuz herhangi bir özel sabun api için zorunlu mudur, yani save (), delete () etc?
Sushivam

Magento 2'de nasıl özel sabun api oluşturulacağı hakkında bir fikir verebilir misiniz?
Sushivam

@SachinS Maalesef, SOAP ile ilgili teklif edebileceğim bir görüş yok. Henüz araştırmadım, henüz uygulamadım. Önerebileceğim en iyi şey, bununla ilgili yeni bir soru açmak olabilir. Belgeleri de kontrol etsem söyleyebilirim, ama bu ne yazık ki her zaman en iyi eylem planı değil (eksik olabilir). Her zaman çekirdek kod tabanına veya bir üçüncü taraf uzantısına bakabilir ve orada herhangi bir görüş olup olmadığını görebilirsiniz. İyi şanslar! Cevabınızı bulursanız, bağlantıyı buraya eklemek güzel olabilir. Thanks
ryanF

@Ryan cevabı için teşekkürler, yine de REST kullanarak modülümü uyguladım, çünkü hafifliği SOAP'a göre daha ağırdı ... Aynı şeyi
SOAP'ta da uygularsam

3
@ryanF Bu çok yararlı cevap için teşekkürler. Çalışma kodunun kopyala / yapıştır olması gerekmediğini biliyorum, ancak ilerde takip edenlerin yararına birkaç yazım hatası var. Depoda, CustomSearchResultsInterfaceFactory, CustomSearchResultsFactory olmalıdır. $ searchResults-> setCriteria, $ searchResults-> setSearchCriteria olmalıdır. $ Foreach içindeki gümrük [] $ gümrük [] olmalıdır. Sanırım bu konuda.
tetranz

3

servis sözleşmelerinin kullanımının eksiksiz dosyaları

Özel / Modül / 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 / Veri / 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");
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.