Magento2 は特定の ExtensionFactory と ExtensionAttributeInterface をどのように生成しますか?
-
19-12-2019 - |
質問
たとえば見積項目などに拡張属性を使用して考えてみたいと思います。
Magento 1 のようなセットアップ クラスを使用して、そのようなエンティティにカスタム属性を追加するのは問題ありません。これはこの質問の内容ではありません。
現時点では、エンティティ API を介して拡張機能によって追加された属性を拡張属性として公開したいとき、その魔法に圧倒されます。
アップデート: 通常の工場がどのように生成されるかを知っています。この質問は、生成された拡張属性インターフェイスの生成された実装をインスタンス化する特別なファクトリーに関するものです。
これを機能させるために私が行う手順は次のとおりです。これらを追加しているのは、答えようとする人が詳細に立ち入る必要がないためです。
私の質問は どうやって または なぜ それは動作します。
エンティティ API を介して拡張属性を公開する手順:
- を作成します
etc/extension_attributes.xml
エンティティインターフェイスに属性を追加します - 属性値をエンティティに追加するプラグインを作成する
ExtensionAttributes
実例。
2 番目の点を実行するには、エンティティ ExtensionAttributes
インスタンスが必要です。このため、プラグインはオブジェクト マネージャーが DI 経由で提供するファクトリに依存します。
お見積り項目例の場合 Magento\Quote\Api\Data\CartItemExtensionFactory
使用する必要があります。
おそらくこの工場の種類が生成魔法のトリガーになっているのだろう。
その後、Magento が一致するインターフェイスを生成します \Magento\Quote\Api\Data\CartItemExtensionInterface
すべての拡張属性のセッターとゲッターを使用します。
ただし、そのインターフェイスの具体的な実装は生成されないようです。少なくともPHPStormはそれを認識していません。
Magento はクラスを生成するために必要な情報をどのように収集しますか?生成されたインターフェイス メソッドを具体的なインスタンスで呼び出すにはどうすればよいでしょうか?メモリ内にのみ生成されるクラスですか?
機能するのは嬉しいですが、本当に満足できるものではありません。拡張機能によって自動的に作成された属性を使用する Magento の機能が、成功の重要な要素の 1 つです。モジュール開発者として、プロセス全体を完全に理解する必要があると考えています。
時間があれば自分で詳しく調べたいと思いますが、できれば説明を聞いていただければ幸いです。
更新 2:読み進めるのに少し時間がかかりました \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator
そして \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator
. 。これで、何が起こっているのか、少なくとも大まかには理解できました。誰も私に勝てない場合は、参考になると思うので、一度完全なプロセスの説明を書きます。
解決
まず第一に、クラス名のサフィックスに基づいて自動生成が行われます。 Factory
, ExtensionInterface
(見る \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::EXTENSION_INTERFACE_SUFFIX
) または Extension
(見る \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::EXTENSION_SUFFIX
).
ここのサフィックスに基づいて適切なジェネレーターが選択されます \Magento\Framework\Code\Generator::generateClass
.
Magento モードが次であると仮定しましょう。 developer
不足しているクラスはその場で生成できます (コンパイラを使用する場合も同様のプロセスが発生します)。オブジェクトマネージャーがインスタンス化しようとしたときのことを考えてみましょう Magento\Quote\Api\Data\CartItemExtensionFactory
それが存在しない場合、次のことが起こります。
- オートローダーはクラスのインスタンス化に失敗し、ここでコード生成を開始します
\Magento\Framework\Code\Generator\Autoloader::load
- 次に、クラス接尾辞は次のように決定されます。
Factory
(宣言されたすべてのサフィックスのリストはここにあります)\Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator
) および対応するファクトリ ジェネレーター クラス (Magento\Framework\ObjectManager\Code\Generator\Factory
) 欠落しているファクトリを生成するために使用されます - すべての自動生成クラスは常に別のクラスに基づいています。ファクトリの場合、ソース クラス名は削除するだけで計算されます。
Factory
サフィックス、それはMagento\Quote\Api\Data\CartItemExtension
. 。このクラスは存在しないため、オートローダーによって自動生成が再度呼び出されますが、今回は Extension クラスに対して行われます。 - 今のサフィックスは
Extension
そして\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator
このクラスを生成するために使用されます - 拡張クラス生成のソースクラスは次のように計算されます。
Magento\Quote\Api\Data\CartItemInterface
, 、それは存在し、拡張クラスは正常に生成されます。ただし、拡張クラス ファイルをインクルードしようとすると、自動生成が再度トリガーされます。Magento\Quote\Api\Data\CartItemExtension
実装するMagento\Quote\Api\Data\CartItemExtensionInterface
, 、存在しません - サフィックスは
ExtensionInterface
そして\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator
生成に使用されます - ExtensionInterface クラスと Extension クラスは、からの情報に基づいて生成されます。
extension_attributes.xml
, 、経由でアクセス可能\Magento\Framework\Api\ExtensionAttribute\Config
, 、その後、ファクトリーが生成されます
重要な注意点の 1 つは、ExtensionInterface には優先順位がないことです。 di.xml
Extension と ExtensionInterface の両方が自動生成されるためです。ExtentionInterface はコンストラクトを介して直接挿入されることが想定されていないため、これは問題ではありません。
他のヒント
私にとって、今夜、@Alex からの回答に加えて、次の行が表示されます
$modelReflection = new \ReflectionClass($extensibleClassName);
if ($modelReflection->isInterface()
&& $modelReflection->isSubclassOf(self::EXTENSIBLE_INTERFACE_NAME)
&& $modelReflection->hasMethod('getExtensionAttributes')
) {
$this->classInterfaceMap[$extensibleClassName] = $extensibleClassName;
return $this->classInterfaceMap[$extensibleClassName];
}
クラスで \Magento\Framework\Api\ExtensionAttributesFactory
拡張インターフェイスが生成されない場合は、ここからデバッグを開始するとよいでしょう。拡張属性のほとんどは、Magento 2 が期待するようなクラスの構造化に関係します。
これらの行は次のように言っています。
extension_attributes のクラスはインターフェイスです
\Magento\Framework\Api\ExtensibleDataInterface を拡張しますか
このインターフェイスには getExtensionAttributes という関数があります