Je voudrais faire le tour de ma tête en utilisant des attributs d'extension, par exemple pour les éléments de devis.
Ce n'est pas un problème d'ajouter un attribut personnalisé à une telle entité en utilisant une classe d'installation comme dans Magento 1, ce n'est pas de cela qu'il s'agit.
En ce moment, la magie me submerge quand je veux exposer un tel attribut qui a été ajouté par une extension via l'API d'entités comme attribut d'extension.
MISE À JOUR : Je sais comment les usines régulières sont générées. Cette question concerne les usines spéciales qui instancient les implémentations générées pour les interfaces d'attribut d'extension générées.
Voici les étapes que je prends pour le faire fonctionner. J'ajoute ces informations afin que quiconque tente de répondre n'ait pas besoin d'entrer dans ces détails.
Ma question est COMMENT ou POURQUOI cela fonctionne.
Étapes pour exposer un attribut d'extension via une API d'entité:
- Créer un
etc/extension_attributes.xml
qui ajoute l'attribut à l'interface d'entité - Créez un plugin pour ajouter la valeur d'attribut à l'
ExtensionAttributes
instance d' entités .
Pour faire le deuxième point, l' ExtensionAttributes
instance d' entités est nécessaire. Pour cette raison, le plugin dépend d'une usine, que le gestionnaire d'objets fournit via DI.
Pour l'exemple d'article de devis Magento\Quote\Api\Data\CartItemExtensionFactory
doit être utilisé.
Je suppose que le type de cette usine doit en quelque sorte être le déclencheur de la magie de génération.
Magento génère ensuite l'interface correspondante \Magento\Quote\Api\Data\CartItemExtensionInterface
avec les setters et les getters pour tous les attributs d'extension.
Cependant, il ne semble pas générer l'implémentation concrète de cette interface. Au bail, PHPStorm ne le voit pas.
Comment Magento collecte-t-il les informations dont il a besoin pour générer la classe? Comment appeler les méthodes d'interface générées sur une instance concrète? Est-ce une classe qui est uniquement générée en mémoire?
Je suis content que ça marche, mais ce n'est pas vraiment satisfaisant. La capacité de Magentos à utiliser des attributs créés automatiquement par des extensions est un facteur clé de son succès. En tant que développeur de modules, je pense avoir besoin d'une compréhension approfondie de l'ensemble du processus.
Si j'avais le temps, je creuserais cela moi-même, mais je préférerais que je puisse simplement obtenir une explication.
MISE À JOUR 2 : A pris un peu de temps pour lire \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator
et \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator
. Maintenant, j'ai au moins une idée approximative de ce qui se passe. Si personne ne me bat, j'écrirai une description du processus complet à un moment donné, car je pense que ce serait une référence utile.
Réponses:
Tout d'abord, la génération automatique se produit en fonction du suffixe du nom de classe, par exemple
Factory
,ExtensionInterface
(voir\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::EXTENSION_INTERFACE_SUFFIX
) ouExtension
(voir\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::EXTENSION_SUFFIX
).Le générateur approprié est sélectionné en fonction du suffixe ici
\Magento\Framework\Code\Generator::generateClass
.Supposons que le mode Magento soit activé
developer
et que les classes manquantes puissent être générées à la volée (un processus similaire se produira lorsque le compilateur sera utilisé). Lorsque le gestionnaire d'objets tente d'instancier, disonsMagento\Quote\Api\Data\CartItemExtensionFactory
et qu'il n'existe pas, les événements suivants se produisent:\Magento\Framework\Code\Generator\Autoloader::load
Factory
(la liste de tous les suffixes déclarés peut être trouvée ici\Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator
) et la classe de générateur Factory correspondante (Magento\Framework\ObjectManager\Code\Generator\Factory
) est utilisée pour générer la fabrique manquanteFactory
suffixe, ce sera le casMagento\Quote\Api\Data\CartItemExtension
. Cette classe n'existe pas et la génération automatique est à nouveau invoquée par l'autochargeur, mais cette fois pour la classe ExtensionExtension
et\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator
sera utilisé pour générer cette classeMagento\Quote\Api\Data\CartItemInterface
, elle existe et la classe d'extension est correctement générée. Cependant, lors de la tentative d'inclusion du fichier de classe d'extension, la génération automatique est déclenchée une fois de plus carMagento\Quote\Api\Data\CartItemExtension
implémenteMagento\Quote\Api\Data\CartItemExtensionInterface
, qui n'existe pasExtensionInterface
et\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator
sera utilisé pour la générationextension_attributes.xml
, accessibles via\Magento\Framework\Api\ExtensionAttribute\Config
, puis Factory est généréUne remarque importante est qu'il n'y a pas de préférence pour ExtensionInterface dans
di.xml
car Extension et ExtensionInterface sont générés automatiquement. Ce n'est pas un problème car ExtentionInterface ne devrait pas être injecté directement via la construction.la source
Pour moi, ce soir, en plus de la réponse de @Alex, je peux voir les lignes
dans la classe
\Magento\Framework\Api\ExtensionAttributesFactory
C'est là que nous pouvons vouloir déboguer si l'interface d'extension n'est pas générée. À peu près les attributs d'extension consistent à structurer notre classe comme Magento 2 s'y attendra.
ces lignes disent:
est la classe dans notre extension_attributes une interface
est-ce qu'il étend \ Magento \ Framework \ Api \ ExtensibleDataInterface
a cette interface une fonction appelée getExtensionAttributes
la source