Was ist der Unterschied zwischen type und virtualType?

41

Im di.xmlLieferumfang von Magento2 gibt es einen Knoten typeund einen Knoten virtualType. Meine Frage ist, was ist das virtualTypeund in welchem ​​Fall sollte es stattdessen verwendet werden type?

An einigen Stellen sieht es aus wie ein symbolischer Link oder ein Umschreiben:

<virtualType name="Magento\Core\Model\Session\Storage" type="Magento\Framework\Session\Storage">

Wenn ein vollständiger Pfad in einen anderen geändert wird, aber an anderen Stellen, scheint er als Methode zum Definieren eines kürzeren Alias ​​verwendet zu werden.

<virtualType name="lessFileSourceBase" type="Magento\Framework\View\File\Collector\Base">
David Manners
quelle
3
Ich habe keine Ahnung , (noch) nicht, was sie bedeuten auch , aber Sie können starten von hier zu graben: Magento\Framework\ObjectManager\Config\Mapper\Dom::convert. switchIrgendwo drin steht eine Aussage.
Marius
Danke @Marius, ich frage mich auch, ob lessFileSourceBasedas auf die xml beschränkt ist oder ob das auch draußen verwendet werden kann. Schätze, ich muss besser graben.
David Manners

Antworten:

83

Virtuelle Typen sind eine Möglichkeit, verschiedene Abhängigkeiten in vorhandene Klassen einzufügen, ohne andere Klassen zu beeinflussen.

Beispielsweise nimmt die Magento\Framework\Session\StorageKlasse $namespacein ihrem Konstruktor ein Argument an, das standardmäßig den Wert 'default' hat, und Sie können die typeDefinition verwenden, um den Namespace in 'core' zu ändern.

<type name="Magento\Framework\Session\Storage">
    <arguments>
        <argument name="namespace" xsi:type="string">core</argument>
    </arguments>
</type>

Die obige Konfiguration würde es so machen, dass alle Instanzen von Magento\Framework\Session\Storageeinen Namespace von 'core' haben. Bei Verwendung eines virtuellen Typs kann das Äquivalent einer Unterklasse erstellt werden, wobei nur die Unterklasse die geänderten Argumentwerte aufweist.

In der Codebasis sehen wir die folgenden zwei Konfigurationen:

<virtualType name="Magento\Core\Model\Session\Storage" type="Magento\Framework\Session\Storage">
    <arguments>
        <argument name="namespace" xsi:type="string">core</argument>
    </arguments>
</virtualType>

<type name="Magento\Framework\Session\Generic">
    <arguments>
        <argument name="storage" xsi:type="object">Magento\Core\Model\Session\Storage</argument>
    </arguments>
</type>

Das erste Snippet erstellt einen virtuellen Typ, für Magento\Core\Model\Session\Storageden der Namespace geändert wird, und das zweite Snippet fügt den virtuellen Typ ein Magento\Framework\Session\Generic. Dies ermöglicht Magento\Framework\Session\Genericdas Anpassen, ohne andere Klassen zu beeinflussen, von denen ebenfalls eine Abhängigkeit deklariert wirdMagento\Framework\Session\Storage

Chris O'Toole
quelle
Vielen Dank @ Chris endlich eine logische Begründung, die ich gefunden habe
Suman-PHP4U
Das war einfach und die beste Demonstration.
Umar
Diese Antwort ist besser als das offizielle Dokument von Magento
Suman-PHP4U
<type>verwendet eine virtuelle Klasse, die eigentlich nicht existiert. Auf diese Weise wird die Änderung des Arguments virtualTypenur wirksam, wenn die Klasse, die den virtualType verwendet, initialisiert wird, wie Magento\Framework\Session\Genericim Beispiel
Arif Ahmad,
21

Ein anderer Weg, virtuelle Typen zu verstehen -

Angenommen, Sie haben eine Klasse \Class1mit dem folgenden Konstruktor:

public function __construct(\Class2 $argOfClass1){...}

Und \Class2hat den folgenden Konstruktor -

public function __construct(\Class3 $argOfClass2){...}

Jetzt wollen Sie die Art der Änderungen $argOfClass2aus \Class3zu \Class4, aber nur , wenn \Class2verwendet , wie $argOfClass1.

Der "alte" Weg, dies zu tun, besteht darin, Folgendes hinzuzufügen di.xml:

<type name="Class1">
    <arguments>
         <argument name="argOfClass1" xsi:type="object">Class5</argument>
    </arguments>
</type>

wo \Class5ist das folgende:

class \Class5 extends \Class2{
    public function __construct(\Class4 $argOfClass2){...}
}

Anstatt diese Methode zu verwenden, können Sie die virtuellen Typen verwenden , um dasselbe zu erreichen, indem Sie Folgendes hinzufügen di.xml:

<virtualType name="Class5" type="Class2">
    <arguments>
        <argument name="argOfClass2" xsi:type="string">Class4</argument>
    </arguments>
</virtualType>

<type name="Class1">
    <arguments>
         <argument name="argOfClass1" xsi:type="object">Class5</argument>
    </arguments>
</type>

Wie Sie sehen können, haben Sie mit dem virtuellen Typ die Arbeit der Erstellung von gespeichert Class5.

Als weitere Referenz schlage ich vor, den Artikel von Alan Storm über virtuelle Typen in Magento2 zu lesen - http://alanstorm.com/magento_2_object_manager_virtual_types/

NoamN
quelle
1
Gute Verbreitung,
Anand Ontigeri
Einfach zu verstehen. Vielen Dank, dass Sie ein so einfaches Beispiel gegeben haben.
Kalyan Chakravarthi V
10

In der gleichen di.xmlDatei habe ich festgestellt, dass lessFileSourceBaseals Argument für übergeben wird, lessFileSourceBaseFiltereddass als Argument für übergeben wird, lessFileSourceBaseSorteddass als Argument für Typ übergeben wird Magento\Framework\Less\File\Collector\Aggregated.

Ich habe kein anderes Vorkommen von lessFileSourceBase(oder lessFileSource) in einer anderen Datei gefunden, außer di.xmlim Kernmodul. Nur in einigen Cache-Dateien sind diese aber nicht wichtig.

Ich denke, wenn Sie den virtuellen Typ nicht in einer PHP-Klasse verwenden, sondern nur in den diXML-Dateien, müssen Sie ihn nicht wie einen Klassennamen aussehen lassen, und Sie können einen Alias ​​verwenden.

Dies ist jedoch nur reine Spekulation.
Es wird "Spaß" machen, zu versuchen, eine Klasse zu erstellen und in ihren Konstruktor eine Instanz von einzufügen, um lessFileSourceBasezu sehen, wie sie sich verhält.

Marius
quelle
1
Sie haben die Anführungszeichen um das Wort Spaß verpasst;)
David Manners
1
@ DavidManners. Richtig. Ich habe es repariert. :)
Marius
@Marius: Wenn Sie alte \Magento\Framework\Session\GenericQuelldatei hängen von Magento\Core\Model\Session\Storagestatt StorageInterfacesollten Sie eine bekommen ‚Klasse Magento \ Core \ Modell \ Session \ Storage ist nicht vorhanden‘ Ausnahme. Der Grund dafür ist, dass ObjectManager keine Instanz von virtualType erstellt, sondern nur ermittelt, welche Argumente für den Konstruktor des konkreten Typs bereitzustellen sind, auf den in der virtualType-Definition verwiesen wird ( Magento\Framework\Session\Storagefür das obige Beispiel).
Chris O'Toole
Dies wird in der Factory angezeigt , wo $requestedTypeder virtuelle Typ dargestellt wird und zum Sammeln von Argumenten verwendet $typewird. Dies ist jedoch der konkrete Typ, dem der virtualType zugeordnet ist und der für den Objektinstanziierungsaufruf verwendet wird.
Chris O'Toole
Selbst wenn lessFileSourceBasees sich um einen Namespace \ class-Typ handelte, würde es keinen direkten Verweis durch eine andere PHP-Klasse zulassen, nur zur Injektion über die di.xml
Chris O'Toole