Pregunta

Me gustaría entender cómo utilizar atributos de extensión, por ejemplo, para elementos de cotización.
No hay problema en agregar un atributo personalizado a dicha entidad usando una clase de configuración como en Magento 1, no se trata esta pregunta de esto.
En este momento, la magia me abruma cuando quiero exponer un atributo que fue agregado por una extensión a través de la API de entidades como un atributo de extensión.

ACTUALIZAR: Sé cómo se generan las fábricas regulares.Esta pregunta trata sobre las fábricas especiales que crean instancias de las implementaciones generadas para las interfaces de atributos de extensión generadas.

Estos son los pasos que sigo para que funcione.Los agrego para que quien intente responder no necesite entrar en esos detalles.
Mi pregunta es CÓMO o POR QUÉ funciona.

Pasos para exponer un atributo de extensión a través de una API de entidad:

  1. Crear un etc/extension_attributes.xml que agrega el atributo a la interfaz de la entidad
  2. Cree un complemento para agregar el valor del atributo a las entidades. ExtensionAttributes instancia.

Para hacer el segundo punto, las entidades ExtensionAttributes Se necesita instancia.Por este motivo, el complemento depende de una fábrica que el administrador de objetos proporciona a través de DI.

Para el ejemplo del artículo de cotización Magento\Quote\Api\Data\CartItemExtensionFactory tiene que ser usado.
Supongo que el tipo de esta fábrica debe ser de alguna manera el desencadenante de la magia generacional.

Magento luego genera la interfaz correspondiente \Magento\Quote\Api\Data\CartItemExtensionInterface con los definidores y captadores para todos los atributos de extensión.
Sin embargo, no parece generar la implementación concreta para esa interfaz.Al menos PHPStorm no lo ve.

¿Cómo recopila Magento la información que necesita para generar la clase?¿Cómo se pueden invocar los métodos de interfaz generados en una instancia concreta?¿Es una clase que simplemente se genera solo en la memoria?

Estoy feliz de que funcione, pero eso no es realmente satisfactorio.La capacidad de Magentos para utilizar atributos creados automáticamente por extensiones es un factor clave para su éxito.Como desarrollador de módulos, creo que necesito una comprensión profunda de todo el proceso.
Si tuviera tiempo, investigaría esto yo mismo, pero preferiría poder obtener una explicación.

ACTUALIZACIÓN 2:Tomó un poco de tiempo para leer \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator y \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator.Ahora al menos tengo una idea aproximada de lo que está pasando.Si nadie se me adelanta, escribiré una descripción del proceso completo en algún momento, ya que creo que sería una referencia útil.

¿Fue útil?

Solución

En primer lugar, la generación automática se produce según el sufijo del nombre de la clase, p. Factory, ExtensionInterface (ver \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::EXTENSION_INTERFACE_SUFFIX) o Extension (ver \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::EXTENSION_SUFFIX).

El generador adecuado se selecciona según el sufijo aquí \Magento\Framework\Code\Generator::generateClass.

Supongamos que el modo Magento está developer y las clases faltantes se pueden generar sobre la marcha (se producirá un proceso similar cuando se utilice el compilador).Cuando el administrador de objetos intenta crear una instancia, digamos Magento\Quote\Api\Data\CartItemExtensionFactory y no existe, sucede lo siguiente:

  1. El cargador automático no puede crear una instancia de la clase e inicia la generación de código aquí \Magento\Framework\Code\Generator\Autoloader::load
  2. Entonces el sufijo de clase se determina como Factory (la lista de todos los sufijos declarados se puede encontrar aquí \Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator) y la clase de generador de fábrica correspondiente (Magento\Framework\ObjectManager\Code\Generator\Factory) se utiliza para generar fábrica faltante
  3. Todas las clases generadas automáticamente siempre se basan en otras clases; en el caso de fábrica, el nombre de la clase fuente se calcula simplemente eliminando Factory sufijo, será Magento\Quote\Api\Data\CartItemExtension.Esta clase no existe y el cargador automático invoca la generación automática una vez más, pero esta vez para la clase de extensión.
  4. Ahora el sufijo es Extension y \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator se utilizará para generar esta clase
  5. La clase fuente para la generación de clases de extensión se calcula como Magento\Quote\Api\Data\CartItemInterface, existe y la clase de extensión se genera correctamente.Sin embargo, al intentar incluir el archivo de clase de extensión, la generación automática se activa una vez más porque Magento\Quote\Api\Data\CartItemExtension implementos Magento\Quote\Api\Data\CartItemExtensionInterface, que no existe
  6. El sufijo es ExtensionInterface y \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator será utilizado para la generación
  7. Las clases ExtensionInterface y Extension se generan en función de la información de extension_attributes.xml, accesible a través de \Magento\Framework\Api\ExtensionAttribute\Config, luego se genera Factory

Una nota importante es que no hay preferencia por ExtensionInterface en di.xml porque tanto Extension como ExtensionInterface se generan automáticamente.Esto no es un problema porque no se espera que ExtensionInterface se inyecte directamente mediante la construcción.

Otros consejos

Para mí, esta noche, además de la respuesta de @Alex, puedo ver las líneas

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

en la clase \Magento\Framework\Api\ExtensionAttributesFactory

es donde es posible que queramos comenzar a depurar si la interfaz de extensión no se genera.Prácticamente los atributos de extensión tratan de estructurar nuestra clase como lo esperará Magento 2.

estas líneas dicen:

  • es la clase en nuestra extensión_attributes una interfaz

  • ¿Extiende \Magento\Framework\Api\ExtensibleDataInterface?

  • tiene esta interfaz una función llamada getExtensionAttributes

Licenciado bajo: CC-BY-SA con atribución
No afiliado a magento.stackexchange
scroll top