Quelle est la difference entre type et virtualType


41

Dans di.xmlMagento2, il existe un nœud typeet un nœud virtualType. Ma question est qu'est-ce que c'est virtualTypeet dans quel cas devrait-il être utilisé à la place de type?

À certains endroits, cela ressemble à un lien symbolique ou à une réécriture:

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

Lorsqu'un chemin complet est modifié en un autre mais qu'à d'autres endroits, il semble être utilisé pour définir un alias plus court.

<virtualType name="lessFileSourceBase" type="Magento\Framework\View\File\Collector\Base">

3
Je ne sais pas (encore) ce qu'ils veulent dire , mais vous pouvez même commencer à creuser d'ici: Magento\Framework\ObjectManager\Config\Mapper\Dom::convert. Il y a une switchdéclaration quelque part.
Marius

Merci @Marius, je me demande également si lessFileSourceBaseest limité au xml ou s'il peut également être utilisé à l'extérieur. Je suppose que je ferais mieux de creuser.
David Manners

Réponses:


84

Les types virtuels sont un moyen d'injecter différentes dépendances dans les classes existantes sans affecter les autres classes.

Par exemple, la Magento\Framework\Session\Storageclasse prend un $namespaceargument dans son constructeur, qui prend par défaut la valeur 'default', et vous pouvez utiliser la typedéfinition pour modifier l'espace de nom en 'core'.

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

La configuration ci-dessus ferait en sorte que toutes les instances de Magento\Framework\Session\Storageont un espace de noms de 'noyau'. L'utilisation d'un type virtuel permet de créer l'équivalent d'une sous-classe, seule la sous-classe ayant les valeurs d'argument modifiées.

Dans la base de code, nous voyons les deux configurations suivantes:

<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>

Le premier extrait crée un type virtuel pour Magento\Core\Model\Session\Storagelequel modifie l'espace de nom, et le second injecte le type virtuel dans Magento\Framework\Session\Generic. Cela permet Magento\Framework\Session\Genericd’être personnalisé sans affecter les autres classes qui déclarent également une dépendance àMagento\Framework\Session\Storage


Merci beaucoup @Chris enfin une justification logique que j'ai trouvée
Suman-PHP4U

C'était simple et la meilleure démonstration.
Umar

Cette réponse est meilleure que la documentation officielle de Magento
Suman-PHP4U

<type>utilise une classe virtuelle qui n'existe pas réellement. De cette façon, la modification d'argument virtualTypene prendra effet que lorsque la classe utilisant le virtualType sera initialisée, comme Magento\Framework\Session\Genericdans l'exemple
Arif Ahmad

21

Une autre façon de comprendre les types virtuels -

Disons que vous avez une classe \Class1, qui a le constructeur suivant -

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

Et \Class2a le constructeur suivant -

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

Maintenant, vous voulez changer le type de $argOfClass2de \Class3à \Class4, mais seulement quand \Class2est utilisé comme $argOfClass1.

La "vieille" façon de faire serait d’ajouter ce qui suit dans di.xml-

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

\Class5est le suivant:

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

Au lieu d'utiliser cette méthode, vous pouvez utiliser les types virtuels pour accomplir la même chose, en ajoutant ce qui suit 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>

Comme vous pouvez le constater, l’utilisation du type virtuel vous a sauvé le travail de création de Class5.

Pour plus de référence, je suggère de lire l'article d'Alan Storm concernant les types virtuels dans Magento2 - http://alanstorm.com/magento_2_object_manager_virtual_types/


1
bonne expalination,
Anand Ontigeri

Facile à comprendre. Merci de partager un exemple aussi fondamental.
Kalyan Chakravarthi V

10

Dans le même di.xmlfichier, j'ai trouvé que lessFileSourceBasec'est passé comme argument car lessFileSourceBaseFilteredc'est passé comme argument car lessFileSourceBaseSortedc'est passé comme argument pour type Magento\Framework\Less\File\Collector\Aggregated.

Je n'ai trouvé aucune autre occurrence de lessFileSourceBase(ou lessFileSource) dans un autre fichier, à l'exception di.xmldu module de base. Seulement dans certains fichiers de cache mais ceux-ci ne sont pas importants.

Je suppose que si vous n'utilisez pas le type virtuel dans une classe PHP, mais uniquement dans les difichiers xml, vous n'êtes pas obligé de faire en sorte que cela ressemble à un nom de classe et vous pouvez utiliser un alias.

Mais ce n’est que pure spéculation.
Ce sera "amusant" d'essayer de créer une classe et d'injecter dans son constructeur une instance de lessFileSourceBasepour voir comment elle se comporte.


1
vous avez manqué les guillemets autour du mot amusement;)
David Manners

1
@ DavidManners. Droite. Je l'ai corrigé. :)
Marius

@Marius: Si vous modifiez \Magento\Framework\Session\Genericle fichier source en fonction de la Magento\Core\Model\Session\Storageplace, StorageInterfacevous devriez obtenir une exception 'Classe Magento \ Core \ Modèle \ Session \ Storage n'existe pas'. La raison étant que ObjectManager ne crée pas d'instance de virtualType, mais l'utilise simplement pour déterminer les arguments à fournir pour le constructeur du type concret référencé par la définition de virtualType ( Magento\Framework\Session\Storagepour l'exemple ci-dessus).
Chris O'Toole

Peut voir cela dans la fabrique , où $requestedTypereprésente le type virtuel et est utilisé pour rassembler des arguments, mais $typecorrespond au type concret auquel mappe virtualType et est utilisé pour l'appel d'instanciation d'objet.
Chris O'Toole

Donc, même si lessFileSourceBaseétait dans un style de type plus d'espace de noms \ class, cela ne permettrait pas une référence directe par une autre classe php, juste pour une injection via le di.xml
Chris O'Toole
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.