Frage

Ich möchte mich mit Erweiterungsattributen beschäftigen, zum Beispiel für Angebotspositionen.
Es ist kein Problem, einer solchen Entität mithilfe einer Setup-Klasse wie in Magento 1 ein benutzerdefiniertes Attribut hinzuzufügen. Darum geht es in dieser Frage nicht.
Im Moment überwältigt mich die Magie, wenn ich ein solches Attribut, das von einer Erweiterung über die Entities-API hinzugefügt wurde, als Erweiterungsattribut verfügbar machen möchte.

UPDATE: Ich weiß, wie die regulären Fabriken erzeugt werden.Diese Frage bezieht sich auf die speziellen Fabriken, die die generierten Implementierungen für die generierten Erweiterungsattributschnittstellen instanziieren.

Hier sind die Schritte, die ich unternehme, um es zum Laufen zu bringen.Ich füge diese hinzu, damit jeder, der versucht zu antworten, nicht auf diese Details eingehen muss.
Meine Frage ist WIE oder WARUM es funktioniert.

Schritte zum Bereitstellen eines Erweiterungsattributs über eine Entitäts-API:

  1. Erstellen Sie eine etc/extension_attributes.xml das fügt das Attribut der Entitätsschnittstelle hinzu
  2. Erstellen Sie ein Plugin, um den Attributwert zu den Entitäten hinzuzufügen ExtensionAttributes Instanz.

Um den zweiten Punkt zu tun, die Entitäten ExtensionAttributes instanz benötigt wird.Aus diesem Grund ist das Plugin auf eine Factory angewiesen, die der Objektmanager über DI liefert.

Für das Angebotspositionsbeispiel Magento\Quote\Api\Data\CartItemExtensionFactory muss benutzt werden.
Ich denke, der Typ dieser Fabrik muss irgendwie der Auslöser für die Generationsmagie sein.

Magento generiert dann die passende Schnittstelle \Magento\Quote\Api\Data\CartItemExtensionInterface mit den Setzern und Gettern für alle Erweiterungsattribute.
Es scheint jedoch nicht die konkrete Implementierung für diese Schnittstelle zu generieren.Zumindest sieht PhpStorm es nicht.

Wie sammelt Magento die Informationen, die es benötigt, um die Klasse zu generieren?Wie können die generierten Schnittstellenmethoden auf einer konkreten Instanz aufgerufen werden?Ist es eine Klasse, die nur im Speicher generiert wird?

Ich bin froh, dass es funktioniert, aber das ist nicht wirklich befriedigend.Die Fähigkeit von Magento, automatisch von Erweiterungen erstellte Attribute zu verwenden, ist ein Schlüsselfaktor für den Erfolg.Als Modulentwickler glaube ich, dass ich ein gründliches Verständnis des gesamten Prozesses brauche.
Sollte ich Zeit haben, würde ich mich einfach selbst damit beschäftigen, aber ich würde es vorziehen, wenn ich nur eine Erklärung bekommen könnte.

AKTUALISIERUNG 2:Es hat ein wenig gedauert, es durchzulesen \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator und \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator.Jetzt habe ich zumindest eine grobe Vorstellung davon, was los ist.Wenn mich niemand schlägt, werde ich an einer Stelle eine Beschreibung des gesamten Prozesses schreiben, da ich denke, dass dies eine nützliche Referenz wäre.

War es hilfreich?

Lösung

Zunächst erfolgt die automatische Generierung basierend auf dem Klassennamensuffix, z. Factory, ExtensionInterface (sehen \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::EXTENSION_INTERFACE_SUFFIX) oder Extension (sehen \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::EXTENSION_SUFFIX).

Der richtige Generator wird hier basierend auf dem Suffix ausgewählt \Magento\Framework\Code\Generator::generateClass.

Nehmen wir an, der Magento-Modus ist developer und fehlende Klassen können im laufenden Betrieb generiert werden (ein ähnlicher Vorgang tritt auf, wenn der Compiler verwendet wird).Wenn der Objektmanager versucht zu instanziieren, sagen wir Magento\Quote\Api\Data\CartItemExtensionFactory und es existiert nicht, folgendes passiert:

  1. Autoloader kann die Klasse nicht instanziieren und initiiert hier die Codegenerierung \Magento\Framework\Code\Generator\Autoloader::load
  2. Dann wird das Klassensuffix bestimmt als Factory (liste aller deklarierten Suffixe finden Sie hier \Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator) und der entsprechenden werkseitigen Generatorklasse (Magento\Framework\ObjectManager\Code\Generator\Factory) wird verwendet, um fehlende Fabrik zu erzeugen
  3. Alle automatisch generierten Klassen basieren immer auf anderen Klassen. Im Falle einer Factory wird der Name der Quellklasse nur durch Entfernen berechnet Factory suffix, es wird sein Magento\Quote\Api\Data\CartItemExtension.Diese Klasse existiert nicht und die automatische Generierung wird erneut vom Autoloader aufgerufen, diesmal jedoch für die Erweiterungsklasse
  4. Jetzt ist das Suffix Extension und \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator wird verwendet, um diese Klasse zu generieren
  5. Die Quellklasse für die Generierung von Erweiterungsklassen wird wie folgt berechnet Magento\Quote\Api\Data\CartItemInterface, es existiert und die Erweiterungsklasse wurde erfolgreich generiert.Beim Versuch, die Erweiterungsklassendatei einzuschließen, wird die automatische Generierung jedoch erneut ausgelöst, weil Magento\Quote\Api\Data\CartItemExtension implementieren Magento\Quote\Api\Data\CartItemExtensionInterface, die nicht existiert
  6. Suffix ist ExtensionInterface und \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator wird für die Erzeugung verwendet
  7. ExtensionInterface und Erweiterungsklassen werden basierend auf Informationen von generiert extension_attributes.xml, erreichbar über \Magento\Framework\Api\ExtensionAttribute\Config, dann wird Fabrik erzeugt

Ein wichtiger Hinweis ist, dass ExtensionInterface in nicht bevorzugt wird di.xml weil sowohl Extension als auch ExtensionInterface automatisch generiert werden.Dies ist kein Problem, da von ExtensionInterface nicht erwartet wird, dass es direkt über das Konstrukt eingefügt wird.

Andere Tipps

Für mich kann ich heute Abend zusätzlich zu der Antwort von @Alex die Zeilen sehen

$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 der Klasse \Magento\Framework\Api\ExtensionAttributesFactory

hier möchten wir möglicherweise mit dem Debuggen beginnen, wenn die Erweiterungsschnittstelle nicht generiert wird.So ziemlich bei Erweiterungsattributen geht es darum, unsere Klasse so zu strukturieren, wie es Magento 2 erwarten wird.

diese Zeilen sagen:

  • ist die Klasse in unseren extension_attributes eine Schnittstelle

  • erweitert es \ Magento\ Framework\ Api\ ExtensibleDataInterface

  • hat diese Schnittstelle eine Funktion namens getExtensionAttributes

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit magento.stackexchange
scroll top