Magento2如何生成具体的ExtensionFactory和ExtensionAttributeInterface?
-
19-12-2019 - |
题
我想使用扩展属性来思考,例如报价项目。
使用像 Magento 1 中那样的设置类向这样的实体添加自定义属性是没有问题的,这不是这个问题的目的。
目前,当我想将扩展通过实体 API 添加的属性作为扩展属性公开时,我感到不可思议。
更新: 我知道常规工厂是如何生成的。这个问题是关于实例化生成的扩展属性接口的生成实现的特殊工厂。
以下是我让它发挥作用所采取的步骤。我添加这些内容是为了让任何试图回答的人都不需要详细说明这些细节。
我的问题是 如何 或者 为什么 有用。
通过实体 API 公开扩展属性的步骤:
- 创建一个
etc/extension_attributes.xml
将属性添加到实体接口 - 创建一个插件以将属性值添加到实体
ExtensionAttributes
实例。
为了实现第二点,实体 ExtensionAttributes
需要实例。因此,插件依赖于对象管理器通过 DI 提供的工厂。
对于报价项目示例 Magento\Quote\Api\Data\CartItemExtensionFactory
必须使用。
我想这个工厂的类型一定是生成魔法的触发器。
Magento然后生成匹配的界面 \Magento\Quote\Api\Data\CartItemExtensionInterface
以及所有扩展属性的 setter 和 getter。
但是,它似乎没有生成该接口的具体实现。至少 PHPStorm 没有看到它。
Magento 如何收集生成类所需的信息?如何在具体实例上调用生成的接口方法?它是一个仅在内存中生成的类吗?
我很高兴它有效,但这并不是真正令人满意。Magentos 使用扩展自动创建的属性的能力是其成功的关键因素之一。作为一名模块开发人员,我相信我需要对整个过程有透彻的了解。
如果我有时间的话,我会自己深入研究这个问题,但我更希望能得到一个解释。
更新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
和\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
, ,然后生成Factory
一个重要的注意事项是,没有对 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 的函数