モデルの新しいエンティティまたは更新されたエンティティを保存するにはどうすればよいですか?


10

Magento 2にはリポジトリクラスがあります。save()Magento 1.9で頻繁に使用されていたクラシックな方法は、私が正しければ2.04または2.05から廃止されます。私はファクトリを使用して新しいオブジェクトを作成し、新しいプロパティを設定した後、たとえば、私が呼び出した製品save()

$productFactory->create()->setName()...->save()

一方、methodを含むリポジトリもありますsave。私はこのように一言でそれを使用しています:

$product = $productFactory->create()->setName()... $productRepository->save($product)

私のコードでは、両方の方法で機能するクラスがあります。また、時には異なる方法が異なる動作を意味することにも気づきました。リポジトリを使用した方法で、データの追加の検証が提供されていますか?

私はそれをどのようにすべきですか?

回答:


10

まず、次のようなモデルでsave()メソッドを直接使用するとどうなるかを見てみましょうproduct

/**
 * @var Magento\Catalog\Model\Product $product
 */
$product->save();

モデルクラス自体は

Magento\Catalog\Model\Product

このクラス内で、save()メソッドの定義を検索します。

見つかりませんでしたか?まあ、beforeSave()とafterSave()はありますが、save()自体はありません。面白いですよね?

次に、の親クラスを確認する必要がありますMagento\Catalog\Model\Product

私たちは、通過する必要があるMagento\Catalog\Model\AbstractModelMagento\Framework\Model\AbstractExtensibleModel最終的に到着しただけに、Magento\Framework\Model\AbstractModel

案の定、ここにsave()メソッドがあり、それは次のようになります

public function save()
{
    $this->_getResource()->save($this);
    return $this;
}

save()が任意のモデルで呼び出されるたびに、これからのsave()メソッドAbstractModelが呼び出され、実装はRESOURCE MODELが実際に保存を行うことがわかります。

Magento 1.0の時間の始まりからと同じように、ほぼすべてのエンティティのモデルとリソースモデルの両方を作成しているため、この最後の1つは常に驚くことではありません。


それでは、どのようにProductRepository機能するか見てみましょう。

ファイルを開きましょう

/vendor/magento/module-catalog/Api/ProductRepositoryInterface.php

このインターフェースは、他のメソッドの中でも特にsave()メソッドがあることを要求します。

このインターフェイスを実際に実装しているのは誰ですか?

ファイルを開きましょう

/etc/di.xml

そして10行目をチェック

<preference for="Magento\Catalog\Api\ProductRepositoryInterface" type="Magento\Catalog\Model\ProductRepository" />

そのため、当然のことながら、save()の方法が内部にあることがわかります。

/vendor/magento/module-catalog/Model/ProductRepository

そしてそれは次のように見えて、444行目から始まります

public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false)
{
    $tierPrices = $product->getData('tier_price');

    try {
    .... other code here ....

このメソッドは、\Magento\Catalog\Api\Data\ProductInterface渡されるタイプの$ productオブジェクトを想定していますが、デフォルトではに解決されますMagento\Catalog\Model\Product

500行目を下に見下ろすと、tryステートメントが表示され、次のようになります。

$this->resourceModel->save($product);

よくわかりました!$this->resourceModelはタイプ77で\Magento\Catalog\Model\ResourceModel\Productprotectedプロパティとして宣言されています。

したがって、繰り返しになりますが、ResourceModel実際には節約が行われます。

しかし、実際には444行目から500行目までがあなたの質問に対する答えです。実際、ここで実行されるすべてのコードは、最終的に、直接モデルの保存とこのリポジトリの保存方法との動作の違いにつながる可能性があります。

たとえば、ignore_links_flagがに設定されている場合、製品リポジトリは製品リンクを取得して処理します。0これが最初から既存の製品かどうかを確認します。

将来的に製品の保存方法を変更する必要がある場合は、おそらく、製品モデルではなく製品リポジトリをオーバーライドすることで、より良い方法であると結論付ける必要があります。

製品の保存と更新についても同様です。製品リポジトリオブジェクトを使用したいのですが。

/vendor/magento/module-cms/Model/PageRepository.phpも参照してください。

これは、CMSページがリポジトリを介して保存される方法です。ここでは、物事はより簡単です。ストアIDが設定され、リソースモデルが呼び出されてすぐに保存されます。

この最後の通知で、リポジトリとモデルの保存にそれほど大きな違いがない場合があると結論付けますが、とにかく、必要なときにいつでもそれらを見つける準備ができていることを願っています。


1

\Magento\Catalog\Api\Data\ProductInterfaceモデルの代わりにデータインターフェイス(など)を直接使用し、リポジトリを使用してモデルをロードおよび保存することをお勧めします。

Magento開発者向けドキュメントを参照


1
わかりました-これはエンティティ全体の正しい方法ですが、一部の属性の値を更新するだけです-エンティティ全体のロード/保存はお勧めしません。
Bartosz Kubicki 16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.