Como o Magento2 gera os ExtensionFactory e ExtensionAttributeInterface específicos?


28

Eu gostaria de entender os atributos de extensão, por exemplo, para itens de cotação.
Não há problema em adicionar um atributo personalizado a uma entidade usando uma classe de instalação como no Magento 1, não é sobre isso que se trata.
No momento, a mágica me impressiona quando quero expor um atributo que foi adicionado por uma extensão por meio da API de entidades como um atributo de extensão.

ATUALIZAÇÃO : Eu sei como as fábricas regulares são geradas. Esta pergunta é sobre as fábricas especiais que instanciam as implementações geradas para as interfaces de atributo de extensão geradas.

Aqui estão os passos que eu tomo para fazê-lo funcionar. Estou adicionando esses itens para que quem tente responder não precise entrar nesses detalhes.
A minha pergunta é COMO ou POR QUE funciona.

Etapas para expor um atributo de extensão por meio de uma API da entidade:

  1. Crie um etc/extension_attributes.xmlque adicione o atributo à interface da entidade
  2. Crie um plug-in para adicionar o valor do atributo à ExtensionAttributesinstância de entidades .

Para fazer o segundo ponto, a ExtensionAttributesinstância de entidades é necessária. Por esse motivo, o plug-in depende de uma fábrica, que o gerenciador de objetos fornece via DI.

Para o item de cotação, o exemplo Magento\Quote\Api\Data\CartItemExtensionFactorydeve ser usado.
Eu acho que o tipo dessa fábrica de alguma forma deve ser o gatilho para a geração mágica.

O Magento gera a interface correspondente \Magento\Quote\Api\Data\CartItemExtensionInterfacecom os setters e getters para todos os atributos de extensão.
No entanto, parece não gerar a implementação concreta para essa interface. No momento, o PHPStorm não está vendo.

Como o Magento coleta as informações necessárias para gerar a classe? Como os métodos de interface gerados podem ser chamados em uma instância concreta? É uma classe que é gerada apenas na memória?

Estou feliz que funcione, mas isso não é realmente satisfatório. A capacidade do Magentos de usar atributos criados automaticamente por extensões é um fator chave para seu sucesso. Como desenvolvedor de módulos, acredito que preciso de um entendimento completo de todo o processo.
Se eu tivesse tempo, eu mesmo iria me aprofundar nisso, mas preferiria se pudesse obter uma explicação.

ATUALIZAÇÃO 2 : Demorou um pouco para ler \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGeneratore ler \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator. Agora, pelo menos, tenho uma ideia aproximada do que está acontecendo. Se ninguém me bater, escreverei uma descrição do processo completo em um ponto, pois acho que seria uma referência útil.


2
fez o The Vinai .. fez a pergunta .. Omg
Amit Bera

Respostas:


26

Antes de tudo, a geração automática está acontecendo com base no sufixo do nome da classe, por exemplo Factory, ExtensionInterface(consulte \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::EXTENSION_INTERFACE_SUFFIX) ou Extension(consulte \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::EXTENSION_SUFFIX).

O gerador apropriado é selecionado com base no sufixo aqui \Magento\Framework\Code\Generator::generateClass.

Vamos assumir que o modo Magento está developere as classes ausentes podem ser geradas em tempo real (processos semelhantes acontecerão quando o compilador for usado). Quando o gerenciador de objetos tenta instanciar, digamos, Magento\Quote\Api\Data\CartItemExtensionFactorye ele não existe, acontece o seguinte:

  1. O carregador automático falha ao instanciar a classe e inicia a geração de código aqui \Magento\Framework\Code\Generator\Autoloader::load
  2. O sufixo da classe é determinado como Factory(a lista de todos os sufixos declarados pode ser encontrada aqui \Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator) e a classe do gerador de Fábrica correspondente ( Magento\Framework\ObjectManager\Code\Generator\Factory) é usada para gerar a falta de fábrica
  3. Todas as classes geradas automaticamente são sempre baseadas em outras classes; no caso de fábrica, o nome da classe de origem é calculado apenas com a remoção do Factorysufixo Magento\Quote\Api\Data\CartItemExtension. Essa classe não existe e a geração automática é invocada mais uma vez pelo carregador automático, mas desta vez para a classe Extension
  4. Agora o sufixo é Extensione \Magento\Framework\Api\Code\Generator\ExtensionAttributesGeneratorserá usado para gerar esta classe
  5. A classe de origem para a geração da classe de extensão é calculada como Magento\Quote\Api\Data\CartItemInterfaceexiste e a classe de extensão é gerada com êxito. No entanto, na tentativa de incluir o arquivo da classe Extension, a geração automática é acionada mais uma vez porque Magento\Quote\Api\Data\CartItemExtensionimplementa Magento\Quote\Api\Data\CartItemExtensionInterface, o que não existe
  6. O sufixo é ExtensionInterfacee \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGeneratorserá usado para geração
  7. As classes ExtensionInterface e Extension são geradas com base em informações de extension_attributes.xml, acessíveis via e \Magento\Framework\Api\ExtensionAttribute\Config, em seguida, o Factory é gerado

Uma observação importante é que não há preferência pelo ExtensionInterface di.xmlporque o Extension e o ExtensionInterface são gerados automaticamente. Isso não é um problema porque não se espera que ExtentionInterface seja injetado diretamente através da construção.


@Vinai, de nada. Bounty foi uma boa surpresa, obrigado. Atualização: apenas para sua informação, se a recompensa foi iniciada após a resposta ter sido aceita, ela não é concedida automaticamente.
Alex Paliarush

0

Para mim, hoje à noite, além da resposta de @Alex, posso ver as linhas

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

na aula \Magento\Framework\Api\ExtensionAttributesFactory

é onde podemos começar a depurar se a interface de extensão não estiver sendo gerada. Praticamente os atributos de extensão são sobre a estruturação de nossa classe, como o Magento 2 espera.

estas linhas estão dizendo:

  • é a classe em nossa extension_attributes uma interface

  • estende \ Magento \ Framework \ Api \ ExtensibleDataInterface

  • possui nessa interface uma função chamada getExtensionAttributes

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.