In che modo Magento2 genera ExtensionFactory e ExtensionAttributeInterface specifici?


28

Vorrei avvolgere la testa usando gli attributi di estensione, ad esempio per le voci di preventivo.
Non è un problema aggiungere un attributo personalizzato a tale entità usando una classe di installazione come in Magento 1, non è questo il problema.
Al momento la magia mi travolge quando voglio esporre un tale attributo che è stato aggiunto da un'estensione tramite l'API delle entità come attributo di estensione.

AGGIORNAMENTO : so come vengono generate le fabbriche regolari. Questa domanda riguarda le fabbriche speciali che istanziano le implementazioni generate per le interfacce degli attributi di estensione generati.

Ecco i passaggi che faccio per farlo funzionare. Sto aggiungendo questi in modo che chiunque tenti di rispondere non abbia bisogno di entrare in quei dettagli.
La mia domanda è COME o PERCHÉ funziona.

Passaggi per esporre un attributo di estensione tramite un'API di entità:

  1. Creare un etc/extension_attributes.xmlche aggiunge l'attributo all'interfaccia entità
  2. Crea un plug-in per aggiungere il valore dell'attributo ExtensionAttributesall'istanza delle entità .

Per fare il secondo punto, ExtensionAttributesè necessaria l' istanza delle entità . Per questo motivo il plugin dipende da una factory, che il gestore oggetti fornisce tramite DI.

Per la citazione Magento\Quote\Api\Data\CartItemExtensionFactorydeve essere usato un esempio.
Immagino che il tipo di questa fabbrica debba in qualche modo essere l'innesco della magia della generazione.

Magento genera quindi l'interfaccia di corrispondenza \Magento\Quote\Api\Data\CartItemExtensionInterfacecon i setter e i getter per tutti gli attributi di estensione.
Tuttavia, non sembra generare l'implementazione concreta per quell'interfaccia. Al momento del noleggio PHPStorm non lo vede.

In che modo Magento raccoglie le informazioni necessarie per generare la classe? Come si possono chiamare i metodi di interfaccia generati su un'istanza concreta? È una classe che viene generata solo in memoria?

Sono felice che funzioni, ma non è molto soddisfacente. La capacità di Magentos di utilizzare gli attributi creati automaticamente dalle estensioni è un fattore chiave per il suo successo. Come sviluppatore di moduli, credo di aver bisogno di una conoscenza approfondita dell'intero processo.
Dovrei avere il tempo di scavare in questo me stesso, ma preferirei se solo potessi ottenere una spiegazione.

AGGIORNAMENTO 2 : ci è voluto un po 'di tempo per leggere \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGeneratore \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator. Ora ho almeno un'idea approssimativa di quello che sta succedendo. Se nessuno mi batte, scriverò una descrizione dell'intero processo ad un certo punto, poiché penso che sarebbe un utile riferimento.


2
Il Vinai ha fatto la domanda .. Omg
Amit Bera

Risposte:


26

Innanzitutto l'autogenerazione avviene in base al suffisso del nome della classe, ad es Factory. ExtensionInterface(Vedi \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::EXTENSION_INTERFACE_SUFFIX) o Extension(vedi \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::EXTENSION_SUFFIX).

Il generatore corretto è selezionato in base al suffisso qui \Magento\Framework\Code\Generator::generateClass.

Supponiamo che la modalità Magento sia developere che le classi mancanti possano essere generate al volo (un processo simile accadrà quando si usa il compilatore). Quando il gestore oggetti tenta di creare un'istanza, supponiamo Magento\Quote\Api\Data\CartItemExtensionFactoryche non esista, si verifica quanto segue:

  1. Il caricatore automatico non riesce a creare un'istanza della classe e avvia qui la generazione del codice \Magento\Framework\Code\Generator\Autoloader::load
  2. Quindi il suffisso di classe viene determinato come Factory(l'elenco di tutti i suffissi dichiarati può essere trovato qui \Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator) e la corrispondente classe del generatore Factory ( Magento\Framework\ObjectManager\Code\Generator\Factory) viene utilizzata per generare factory mancante
  3. Tutte le classi autogenerate si basano sempre su altre classi, in caso di factory, il nome della classe di origine viene calcolato semplicemente rimuovendo il Factorysuffisso, lo sarà Magento\Quote\Api\Data\CartItemExtension. Questa classe non esiste e l'autogenerazione viene nuovamente invocata dal caricatore automatico, ma questa volta per la classe Extension
  4. Ora il suffisso è Extensione \Magento\Framework\Api\Code\Generator\ExtensionAttributesGeneratorverrà utilizzato per generare questa classe
  5. La classe di origine per la generazione della classe di estensione viene calcolata come Magento\Quote\Api\Data\CartItemInterface, esiste e la classe di estensione viene generata correttamente. Tuttavia, nel tentativo di includere il file di classe Extension, l'autogenerazione viene nuovamente attivata perché Magento\Quote\Api\Data\CartItemExtensionimplementa Magento\Quote\Api\Data\CartItemExtensionInterface, che non esiste
  6. Il suffisso è ExtensionInterfacee \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGeneratorsarà utilizzato per la generazione
  7. Le classi ExtensionInterface ed Extension vengono generate in base alle informazioni extension_attributes.xml, accessibili tramite \Magento\Framework\Api\ExtensionAttribute\Config, quindi viene generato Factory

Una nota importante è che non esiste alcuna preferenza per ExtensionInterface di.xmlperché sia ​​Extension che ExtensionInterface sono generati automaticamente. Questo non è un problema perché non si prevede che ExtentionInterface venga iniettato direttamente tramite il costrutto.


@Vinai sei il benvenuto. Bounty è stata una bella sorpresa, grazie. Aggiornamento: solo FYI, se la taglia è stata avviata dopo che la risposta è stata accettata, non viene assegnata automaticamente.
Alex Paliarush,

0

Per me, stasera, in cima alla risposta di @Alex, posso vedere le righe

$modelReflection = new \ReflectionClass($extensibleClassName);
        if ($modelReflection->isInterface()
            && $modelReflection->isSubclassOf(self::EXTENSIBLE_INTERFACE_NAME)
            && $modelReflection->hasMethod('getExtensionAttributes')
        ) {
            $this->classInterfaceMap[$extensibleClassName] = $extensibleClassName;
            return $this->classInterfaceMap[$extensibleClassName];
        }

in classe \Magento\Framework\Api\ExtensionAttributesFactory

è dove potremmo voler iniziare il debug se l'interfaccia di estensione non viene generata. Praticamente gli attributi di estensione riguardano la strutturazione della nostra classe come Magento 2 si aspetta.

queste righe dicono:

  • è la classe nel nostro extension_attributes un'interfaccia

  • estende \ Magento \ Framework \ Api \ ExtensibleDataInterface

  • ha questa interfaccia una funzione chiamata getExtensionAttributes

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.