Magento 2でカスタムモジュールのサービスコントラクトを実装する方法


42

この記事で見られるように:非推奨に保存し、抽象モデルの負荷メソッドsaveloadメソッドは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の優れた答えに加えて、もう少し詳しく説明したいと思います。

カスタムエンティティ用のリポジトリを追加する理由を要約し、その方法の例を示し、Web APIの一部としてこれらのリポジトリメソッドを公開する方法についても説明します。

免責事項:サードパーティのモジュールに対してこれを行う実際的なアプローチのみを説明しています-コアチームは独自の標準に従っています(または準拠していません)。

一般に、リポジトリの目的は、ストレージ関連のロジックを隠すことです。
リポジトリのクライアントは、返されたエンティティが配列内のメモリに保持されているか、MySQLデータベースから取得されているか、リモートAPIまたはファイルから取得されているかを気にするべきではありません。
Magentoのコアチームがこれを行ったため、将来ORMを変更または交換できると思います。Magentoでは、ORMは現在、モデル、リソースモデル、およびコレクションで構成されています。
サードパーティのモジュールがリポジトリのみを使用する場合、Magentoはデータの保存方法と保存場所を変更でき、これらの大きな変更にもかかわらず、モジュールは引き続き機能します。

リポジトリは、一般的のようなメソッドを持ってfindById()findByName()put()またはremove()
Magentoのでは、これらは一般的に呼ばれているgetbyId()save()delete()も、彼らは何かが、CRUD DB操作を行っているふりをしていません、。

Magento 2リポジトリメソッドは、APIリソースとして簡単に公開できるため、サードパーティシステムまたはヘッドレスMagentoインスタンスとの統合に役立ちます。

「カスタムエンティティのリポジトリを追加する必要がありますか?」

いつものように、答えは

"場合によります"。

簡単に言うと、エンティティが他のモジュールで使用される場合、はい、おそらくリポジトリを追加する必要があります。

ここで考慮されるもう1つの要素があります。Magento2では、リポジトリをWeb API(RESTおよびSOAP)リソースとして簡単に公開できます。

サードパーティのシステム統合またはヘッドレスMagentoのセットアップのためにそれがあなたにとって興味深い場合、そして、はい、あなたはおそらくあなたのエンティティのリポジトリを追加したいでしょう。

カスタムエンティティのリポジトリを追加するにはどうすればよいですか?

エンティティをREST APIの一部として公開したいとします。そうでない場合は、インターフェースの作成に関する今後の部分をスキップして、以下の「リポジトリとデータモデルの実装の作成」に直接進んでください。

リポジトリとデータモデルのインターフェイスを作成する

Api/Data/モジュールにフォルダーを作成します。これは単なる慣例であり、別の場所を使用することもできますが、使用しないでください。
リポジトリーはApi/フォルダーに入ります。Data/サブディレクトリが後であります。

Api/、公開するメソッドを使用してPHPインターフェースを作成します。Magento 2の規則に従って、すべてのインターフェイス名はサフィックスで終わりますInterface
たとえば、Hamburgerエンティティの場合、インターフェイスを作成しますApi/HamburgerRepositoryInterface

リポジトリインターフェイスを作成する

Magento 2リポジトリは、モジュールのドメインロジックの一部です。つまり、リポジトリが実装しなければならないメソッドの固定セットはありません。
それは完全にモジュールの目的に依存します。

ただし、実際にはすべてのリポジトリは非常に似ています。これらはCRUD機能のラッパーです。
大半は、メソッドを持ってgetByIdsavedeletegetList
さらに多くの可能性があります。たとえば、CustomerRepositoryメソッドgetには、電子メールで顧客を取得するメソッドがありgetById、エンティティIDで顧客を取得するために使用されます。

ハンバーガーエンティティのリポジトリインターフェースの例を次に示します。

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

}

重要!ここにタイムシンクがあります!
ここには、間違えた場合にデバッグするのが難しいいくつかの落とし穴があります。

  1. しないでください使用PHP7あなたはRESTのAPIにこれをフックしたい場合は、スカラー引数の型または戻り値の型を!
  2. すべてのメソッドにPHPDocアノテーションをすべての引数と戻り値の型に追加してください!
  3. PHPDocブロックで完全修飾クラス名を使用してください!

注釈はMagentoフレームワークによって解析され、JSONまたはXMLとの間でデータを変換する方法を決定します。クラスのインポート(つまり、useステートメント)は適用されません!

すべてのメソッドには、引数の型と戻り値の型を含む注釈が必要です。メソッドが引数を取らず、何も返さない場合でも、アノテーションが必要です。

/**
 * @return void
 */

スカラ型(stringintfloat及びはbool)また、引数の戻り値としても、指定されなければなりません。

上記の例では、オブジェクトを返すメソッドの注釈もインターフェイスとして指定されていることに注意してください。
戻り型のインターフェースはすべてApi\Data名前空間/ディレクトリにあります。
これは、それらにビジネスロジックが含まれていないことを示すためです。それらは単なるデータの袋です。
次にこれらのインターフェイスを作成する必要があります。

DTOインターフェイスを作成する

Magentoはこれらのインターフェイスを「データモデル」と呼んでいると思います。
このタイプのクラスは、一般にデータ転送オブジェクトDTO)として知られています。
これらのDTOクラスには、すべてのプロパティのゲッターとセッターのみがあります。

データモデルよりもDTOを使用する理由は、ORMデータモデル、リソースモデル、またはビューモデルと混同しにくいためです。Magentoのモデルは既に多すぎます。

リポジトリに適用されるPHP7の入力に関する制限は、DTOにも適用されます。
また、すべてのメソッドには、すべての引数タイプと戻り値タイプを含む注釈が必要です。

<?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()andと呼ばれる規則により、別のゲッター/セッターのペアも追加する必要がありsetExtensionAttributes()ます。

このメソッドの戻り値の型の命名は非常に重要です!

Magento 2フレームワークは、適切な名前を付けると、インターフェイス、実装、および実装のファクトリを生成します。ただし、これらのメカニズムの詳細はこの投稿の範囲外です。
拡張可能にしたいオブジェクトのインターフェースが呼び出される\VinaiKopp\Kitchen\Api\Data\HamburgerInterface場合、拡張属性タイプはでなければなりません\VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface。そのため、単語Extensionはエンティティ名の後、Interface接尾辞の直前に挿入する必要があります。

エンティティを拡張可能にしたくない場合、DTOインターフェイスは他のインターフェイスを拡張する必要はなく、getExtensionAttributes()およびsetExtensionAttributes()メソッドは省略できます。

今のところDTOインターフェースについては十分です。リポジトリインターフェースに戻りましょう。

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

このインターフェイスは、2つのメソッド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

リポジトリとデータモデルの実装を作成する

次のステップは、3つのインターフェースの実装を作成することです。

リポジトリ

本質的に、リポジトリは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

特に、コレクションの条件を設定する構文は、EAVかフラットテーブルエンティティかによって異なるため、フィルターの条件ANDOR条件を正しく取得することはトリッキーです。

ほとんどの場合、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;
    }
}

内のフィルターはFilterGroupOR演算子を使用して結合する必要があります。
論理AND演算子を使用して、個別のフィルターグループを結合します。

ふぅ
これは作品の最大のビットでした。他のインターフェイスの実装は単純です。

DTO

Magentoは元々、開発者がエンティティモデルとは異なる別個のクラスとしてDTOを実装することを意図していました。

ただし、コアチームはカスタマーモジュールに対してのみこれを行いました(で\Magento\Customer\Api\Data\CustomerInterface\Magento\Customer\Model\Data\Customerなくによって実装されています\Magento\Customer\Model\Customer)。
他のすべての場合、エンティティモデルはDTOインターフェイスを実装します(たとえば\Magento\Catalog\Api\Data\ProductInterface、によって実装されます\Magento\Catalog\Model\Product)。

私は会議でコアチームのメンバーにこれについて尋ねましたが、良いプラクティスと考えられるものについて明確な応答が得られませんでした。
私の印象では、この推奨事項は放棄されました。ただし、これについて公式の声明を入手できたらうれしいです。

今のところ、モデルをDTOインターフェイスの実装として使用するという実用的な決定を下しました。別のデータモデルを使用する方が簡単だと思う場合は、お気軽にご利用ください。どちらのアプローチも実際にはうまく機能します。

DTOインターフェースがを拡張するMagento\Framework\Api\ExtensibleDataInterface場合、モデルは拡張する必要がありMagento\Framework\Model\AbstractExtensibleModelます。
拡張性を気にしない場合、モデルは単にORMモデルの基本クラスを拡張し続けることができ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);
    }
}

プロパティ名を定数に抽出すると、それらを1つの場所に保持できます。これらは、ゲッター/セッターのペア、およびデータベーステーブルを作成するセットアップスクリプトで使用できます。そうでなければ、それらを定数に抽出しても利点はありません。

SearchResult

SearchResultsInterfaceそれは、フレームワークのクラスからのすべての機能を継承することができるので、実装するの3つのインタフェースの最も単純です。

<?php

namespace VinaiKopp\Kitchen\Model;

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

class HamburgerSearchResult extends SearchResults implements HamburgerSearchResultInterface
{

}

ObjectManagerの設定を構成する

実装が完了したとしても、Magento Frameworkオブジェクトマネージャーはどの実装を使用するのかわからないため、インターフェイスを他のクラスの依存関係として使用することはできません。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>

リポジトリをAPIリソースとして公開するにはどうすればよいですか?

この部分は本当に簡単です。インターフェース、実装、およびそれらを接続するすべての作業を完了することに対する報酬です。

必要なのは、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>

この構成は、リポジトリをRESTエンドポイントとして使用できるようにするだけでなく、SOAP APIの一部としてメソッドも公開することに注意してください。

最初のルート例で<route method="GET" url="/V1/vinaikopp_hamburgers/:id">は、プレースホルダー:idは、マップされたメソッドの引数の名前と一致する必要がありますpublic function getById($id)。メソッド引数の変数名はであるため、
2つの名前は一致する必要/V1/vinaikopp_hamburgers/:hamburgerIdがあり$idます。たとえば、機能しません。

この例では、アクセシビリティをに設定しました<resource ref="anonymous"/>。これは、リソースが制限なしに公開されることを意味します!
ログインした顧客のみがリソースを利用できるようにするには、を使用します<resource ref="self"/>。この場合、meリソースエンドポイントURL の特殊語を使用して$id、現在ログインしている顧客のIDを引数変数に設定します。
Magentoのお客様etc/webapi.xmlをご覧CustomerRepositoryInterfaceください。必要に応じてください。

最後<resources>に、管理ユーザーアカウントへのリソースへのアクセスを制限するためにも使用できます。これを行うには、<resource>refをetc/acl.xmlファイルで定義された識別子に設定します。
たとえば、<resource ref="Magento_Customer::manage"/>顧客を管理する特権を持つ管理者アカウントへのアクセスを制限します。

curlを使用したAPIクエリの例は次のようになります。

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

注:これは答えとして開始書き込みhttps://github.com/astorm/pestle/issues/195
チェックアウト乳棒を、購入Commercebugをとなるpatreon @alanstormの


1
この素晴らしい答えをありがとう。申し訳ありませんが、何か不足しているかもしれませんが、最後にエンティティにsetDataメソッドを持つAbstractModelから拡張する必要がある場合は、インターフェイスに関係なくオブジェクトに何かを追加できることを意味します。
LDusan

クラスは、任意の数のインターフェイスを実装し、メソッドを追加することもできます。重要なことは、他のクラスはインターフェイスメソッドにのみ依存するため、他のクラスについては何も知らないということです。これにより、インターフェース以外のメソッドの実装の詳細が作成され、外部クラスを壊すことなくいつでも変更できます。これが、依存関係の反転の背後にある考え方です。クラスとクライアントの両方がインターフェースに依存しており、実装の詳細については知りません。それは明確ですか?
Vinai

答えてくれてありがとう。問題は、setDataがパブリックメソッドであるため、実装の詳細と見なすことができるかどうかはわかりません。パブリックメソッドのように使用することを意図している場合、どのように変更しても外部に影響を与えないことを確認できますか?
LDusan

3
謝罪します。あなたが説明しているのは、共通の視点です。依存関係のメカニズムは直感的ではなく、PHPはインターフェイスに依存するインターフェイスの一部ではないメソッドの呼び出しを許可するため、またコンパイルする必要がないため、依存関係の動作がさらにぼやけて明確に見えにくくなります。これは、Magento 2コアでも確認できます。Magento2コアでは、インターフェイスに依存する実装の一部ではない実装メソッドが呼び出されます。これらは悪い例として役立ち、明確で健全な理解を得るのをさらに難しくします。
ビナイ


35

デジタルピアニズムの@Raphael:

次のサンプルモジュール構造を参照してください。

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.phphttp : //codepad.org/WognSKnH

  2. SearchResultsInterfaceを作成します
    Namespace/Custom/Api/Data/CustomSearchResultsInterface.phphttp : //codepad.org/zcbi8X4Z

  3. CustomInterface(データコンテナ)の作成
    Namespace/Custom/Api/Data/CustomInterface.phphttp : //codepad.org/Ze53eT4o

  4. CustomRepository(Concrete Repository)を作成します
    Namespace/Custom/Model/CustomRepository.phphttp : //codepad.org/KNt5QAGZ
    これが「魔法」が起こる場所です。コンストラクターDIを介して、カスタムモジュールのリソースモデル/コレクションファクトリーを渡します。CustomRepositoryInterfaceのため、このリポジトリのCRUDメソッドの保存に関しては、CustomInterfaceのパラメーターを渡す必要があります。モジュールのdi.xmlには、このタイプのインターフェースをエンティティモデルに置き換える設定があります。エンティティモデルはリソースモデルに渡され、保存されます。

  5. 環境設定
    Namespace/Custom/etc/di.xmlhttp : //codepad.org/KmcoOUeV

  6. カスタムインターフェースを実装するエンティティモデル(データコンテナ)
    Namespace/Custom/Model/Custom.phphttp://codepad.org/xQiBU7p7

  7. リソースモデル
    Namespace/Custom/Model/ResourceModel/Custom.phphttp : //codepad.org/IOsxm9qW

注意すべきいくつかの点:

  • 免責事項!!! 私はあなたのカスタムベンダー名、代理店名などの代わりに「名前空間」を使用しました...あなたがモジュールをグループ化するために使用する名前は何でも...「名前空間」の実際の使用はPhp では完全に有効ではありません ...私はこれを便宜のためにやったし、これがうまくいくと思わないし、いかなる形でもそれを提案しない。

  • @ライアン・ストリートはこれを教えてくれた...だから私はすべてのクレジットを取るつもりはありません

  • ニーズに合わせてリポジトリの実装を明確に変更します

  • 具体的なリポジトリのカスタムエンティティモデル/リソースモデル/コレクションとの相互作用を実装します...

  • あなたが質問に挙げたすべての方法に取り組んだわけではないことは知っていますが、これは素晴らしい出発点であり、ドキュメントと実際の実装のギャップを埋めるはずです。


ライアン、サービス契約で言及されているメソッドは、save()、delete()など、作成するカスタムSOAP APIに必須ですか?
Sushivam

magento 2でカスタムSOAP APIを作成する方法のアイデアを教えてください。
Sushivam

@SachinS残念ながら、SOAPに関して提供できる洞察はありません。私はまだ調査していませんし、まだ実装していません。私が提案できる最善のことは、それに関する新しい質問をここで開くことです。私もドキュメントをチェックすると言いますが、それは悲しいことに必ずしも最善の行動ではありません(彼らは欠けているかもしれません)。コアコードベースまたはサードパーティの拡張機能を常に確認し、そこに洞察があるかどうかを確認できます。幸運を!答えが見つかったら、ここにリンクを追加するといいかもしれません。ありがとう
-ryanF

返信@ryanのためのおかげで、とにかく私はRESTを使用して、私のモジュールを実装し、SOAPに比べて光加重以来...私はSOAPで同じを実装する場合、病気にそれを投稿
Sushivam

3
@ryanFこの非常に有用な答えをありがとう。私はそれがコピー/貼り付け作業コードであることを想定していないことを知っていますが、ここで他の人の利益のためにいくつかのタイプミスがあります。リポジトリでは、CustomSearchResultsInterfaceFactoryはCustomSearchResultsFactoryである必要があります。$ searchResults-> setCriteriaは$ searchResults-> setSearchCriteriaである必要があります。foreachの$ Customs []は、$ customs []でなければなりません。私はそれについてだと思います。
テトランズ

3

使用サービス契約の完全なファイル

Custom / Module / 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 / Data / 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");
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.