Magento 2でリポジトリとファクトリを使用する場合


75

Magento 2でいくつかのチュートリアルを行ったところ、少し混乱しました。基本的に、ビジネスエンティティを読み書きできる方法は2つあります。

データを取得する

工場アプローチの使用

$object = $this->myFactory->create();
$object->load($myId);

リポジトリアプローチの使用

$repo   = $this->myRepository();
$object = $repo->getById($myId);

データを保存する

工場アプローチの使用

$object = $this->myFactory->create();
$object->load($myId);
$object->setData('something', 'somethingDifferent')->save();

リポジトリアプローチの使用

$repo   = $this->myRepository();
$object = $repo->getById($myId);
$object->setData('something', 'somethingDifferent');
$repo->save($object);

依存関係注入を使用して、リポジトリとファクトリクラスの両方を注入できることもわかります。これは少なくとも私にとって混乱を招きます。

リポジトリアプローチとファクトリアプローチはいつ使用する必要がありますか?従う必要があるベストプラクティスは何ですか?


Factory、CollectionFactory、Repositoryの使用の良い例は、\ Magento \ Setup \ Fixtures \ CategoryResolverで見ることができます
リカルドマルティンス

回答:


72

リポジトリがあり、必要なことを十分に行える場合は、常にリポジトリを優先します。

リポジトリはサービスコントラクトの一部です(これらはのインターフェイスの実装ですApi)。これは、リポジトリが他のモジュールへのパブリックインターフェイスとして意図されていることを意味します。

リポジトリを使用して完全にロードする

$model->load()サービス契約の一部ではありません。その特定のトピックについて質問がありましたが、答えが役立つかもしれません:サービス契約よりも$ model-> load()を好む理由はありますか?

ファクトリーを使用して新しいエンティティを作成する

リポジトリには新しいエンティティを作成するメソッドが付属していないため、その場合はファクトリが必要になります。しかし、次のようなインターフェースのファクトリを使用しますMagento\Catalog\Api\Data\ProductInterfaceFactory -DI構成に基づいて適切な実装を作成します。

次に、repository->save()メソッドを使用して保存します。

さらに制御が必要な場合は、コレクションファクトリを使用します

以下はMagentoの公式のベストプラクティスではありませんが、現在のところ、リポジトリでは何をロードするかを細かく制御することはできません。検索条件APIを使用すると、フィルターを定義できますが、たとえば、特定のEAV属性を選択したり、結合するインデックステーブルを指定したりする方法はありません。

これらはサービスコントラクトAPIからは見えない実装の詳細ですが、多くの場合、これらの実装の詳細は重要であり、無視するとパフォーマンスが低下します。そのため、リポジトリが私を制限しているとすぐに、基になるコレクションを使用することをheしません。


2
Factoriesを使用して新しいエンティティを作成することについてのコード例を教えてください。説明には詳細がなく、理解しにくいものがあります。どうもありがとうございました。
キーシャン


ありがとう。しかし、use the factory for the interface, such as Magento\Catalog\Api\Data\ProductInterfaceFactory - it will create the right implementation based on DI configuration.私が理解できない点ですが、開発者ガイドはInterfaceFactoryを導入していませんrepository->save()。新しいエンティティを保存するためのメソッドの使用方法は?リポジトリではなく、ファクトリのみを使用して新しいエンティティを保存できます。
キーシャン

@Key Shangは、インターフェースがテーブルのすべての列を保存するためのすべての設定データ関数を提供することを意味するため、可能な限りインターフェースを使用して新しいレコードを保存してください。InterfaceFactoryクラスはdi:compileの一部として作成されるため、var / generationフォルダーで確認できます。
stevensagaar

@stevensagaarありがとう、今理解できました。
キーシャン

21

良い質問。

リポジトリとファクトリの両方でエンティティにアクセスできる場合でも、それらの責任に焦点を当てる必要があると思います。

Magentoのドキュメントから「ファクトリーは、注入不可能なクラス、つまりデータベースエンティティーを表すモデルをインスタンス化するサービスクラスです。ObjectManagerとビジネスコードの間に抽象レイヤーを作成します。」

Alan Stormの記事から「リポジトリオブジェクトは、オブジェクトストアへのオブジェクト情報の読み取りと書き込みを担当します」

私の解釈は次のとおりです。注入できない(いわゆる「更新可能」)オブジェクトを処理することが目的の場合は、ファクトリーを使用する必要があります。オブジェクトストア内のオブジェクトの検索/読み取り/書き込みに重点を置いている場合は、リポジトリを使用する必要があります。

これは、トピックに対する私の理想的なアプローチです。アランが指摘したように、実際の実装では、物事を台無しにすることがあります。

楽しい。


5

データの読み取り/書き込みとビジネスロジックの間のコード分離を可能にするため、リポジトリの使用を開始することになると思います。

Alan Stormがこれについて書いた非常に詳細な記事があり、リポジトリの使用方法を説明していますが、この新しい方法の欠点も調べています:http : //alanstorm.com/magento_2_understanding_object_repositories/

また、Magentoのドキュメントから、この新しいアプローチの利点について説明しています:http ://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-contracts.html


2
答えてくれてありがとう。私は実際、アランストームの記事から自分の頭にこの疑念を抱いています。:)
ラジーエフKトミー

3
確かに、それはあなたに考えさせますが、それはおそらく良いことです。これがMagentoによって提案されたベストプラクティスであったとしても、開発者が質問を投げかけたり、その側面を批判したりできないという意味ではありません。また、リポジトリでカバーされていない状況もあります。ただし、リポジトリを使用して将来のリリースで中断しない拡張機能を構築する場合は、考慮する必要があります。また、彼らはさらに開発し、開発者が必要とするものについてより多くの報道を提供すると確信しています。
マリーナビルチャ

私はあなたのコメントに100%同意します。私は本当にそう願っています。また、ファビアンの回答もご覧ください。
ラジーエフKトミー

はい、私は見ました:)すでに彼の答えを支持しました。すばらしい質問をありがとう!
マリーナビルチャ

さらに、インストール/アップグレードスクリプトまたはファクトリーで低レベルのデータ操作方法を使用しも問題ないことをどこかで読み$setup->updateTableRow(...);ましたが、確信はありませんが、高レベルを使用するための引数がその領域にも適用されるように感じますか?
medmek

1

この回答が他の拡張機能開発者にも役立つことを願っています。

リポジトリのみを使用してモデルを保存する必要があります。

  1. Magento 2のファクトリモデルには、非常に限られたデータしかありません。
  2. 一方、顧客、製品などに関連するeav属性の場合、リポジトリモデルにはすべてのデータが含まれます。
  3. モデルの保存では、リポジトリを使用してエンティティを保存します。モデルの保存にファクトリモデルが使用されている場合、そのエンティティに関連するシステム以外のeav属性(顧客、製品など)はすべて削除されます。

  4. モデルを読み込むために、リポジトリはgetById()メソッドを使用してモデルを取得する最適なオプションです。

モデルを保存するために、可能な限りリポジトリを使用することをお勧めします。


1

load、save、deleteメソッド(モデル)は非推奨になりました。リソースモデルまたはリポジトリを使用できます。

Magentoは、保存、削除、読み込み操作にエンティティマネージャーの概念を使用しています。

リソースモデルには、これらの操作を実行するエンティティマネージャーオブジェクトがあります。

$categoryModel = $this->_objectManager->create('\Magento\Catalog\Model\CategoryFactory')->create();        
  $categoryResource = $this->_objectManager->create('\Magento\Catalog\Model\ResourceModel\Category');        
  $categoryResource->load($categoryModel, 3);        
  echo $categoryModel->getName();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.