I would like to wrap my head around using extension attributes, for example for quote items.
It is no problem adding a custom attribute to such an entity using a setup class like in Magento 1, this isn't what this question is about.
At the moment the magic overwhelms me when I want to expose such an attribute that was added by an extension via the entities API as an extension attribute.
UPDATE: I know how the regular factories are generated. This question is about the special factories that instantiate the generated implementations for the generated extension attribute interfaces.
Here are the steps I take to get it to work. I'm adding these so whoever attempts to answer doesn't need to go into those details.
My question is HOW or WHY it works.
Steps for exposing an extension attribute via an entity API:
- Create an
etc/extension_attributes.xml
that adds the attribute to the entity interface - Create a plugin to add the attribute value to the entities
ExtensionAttributes
instance.
In order to do the second point, the entities ExtensionAttributes
instance is needed. For this reason the plugin depends on a factory, which the object manager supplies via DI.
For the quote item example Magento\Quote\Api\Data\CartItemExtensionFactory
has to be used.
I guess the type of this factory somehow must be the trigger for the generation magic.
Magento then generates the matching interface \Magento\Quote\Api\Data\CartItemExtensionInterface
with the setters and getters for all the extension attributes.
However, it does not seem generate the concrete implementation for that interface. At lease PHPStorm isn't seeing it.
How does Magento gather the information it needs to generate the class? How can the generated interface methods be called on a concrete instance? Is it a class that just gets generated in memory only?
I'm happy it works, but that isn't really satisfying. Magentos capability to use attributes created automatically by extensions is one key factor to its success. As a module developer, I believe I need a thorough understanding of the whole process.
Should I have time I'd just dig into this myself, but I would prefer if I just could get an explanation.
UPDATE 2: Took a little time to read through \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator
and \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator
. Now I at least have a rough idea what is going on. If no one beats me to it I'll write a description of the full process at one point, as I think it would be a useful reference.
Best Answer
First of all autogeneration is happening based on class name suffix, e.g.
Factory
,ExtensionInterface
(see\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::EXTENSION_INTERFACE_SUFFIX
) orExtension
(see\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::EXTENSION_SUFFIX
).Proper generator is selected based on suffix here
\Magento\Framework\Code\Generator::generateClass
.Let's assume Magento mode is
developer
and missing classes can be generated on fly (similar process will happen when compiler is used). When object manager tries to instantiate let's sayMagento\Quote\Api\Data\CartItemExtensionFactory
and it does not exist, the following happens:\Magento\Framework\Code\Generator\Autoloader::load
Factory
(list of all declared suffixes can be found here\Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator
) and corresponding Factory generator class (Magento\Framework\ObjectManager\Code\Generator\Factory
) is used to generate missing factoryFactory
suffix, it will beMagento\Quote\Api\Data\CartItemExtension
. This class does not exist and autogeneration is invoked once again by autoloader, but this time for Extension classExtension
and\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator
will be used to generate this classMagento\Quote\Api\Data\CartItemInterface
, it exists and Extension class is successfully generated. However, on the attempt to include Extension class file, autogeneration is triggered once again becauseMagento\Quote\Api\Data\CartItemExtension
implementsMagento\Quote\Api\Data\CartItemExtensionInterface
, which does not existExtensionInterface
and\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator
will be used for generationextension_attributes.xml
, accessible via\Magento\Framework\Api\ExtensionAttribute\Config
, then Factory gets generatedOne important note is that there is no preference for ExtensionInterface in
di.xml
because both Extension and ExtensionInterface are autogenerated. This is not a problem because ExtentionInterface is not expected to be injected via construct directly.