Qual è la differenza tra type e virtualType


41

Nel di.xmlche viene fornito con Magento2 c'è un nodo typee un nodo virtualType. La mia domanda è: cos'è virtualTypee in che caso dovrebbe essere usato al posto di type?

In alcuni punti sembra un collegamento simbolico o riscrivi:

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

Quando un percorso completo viene cambiato in un altro ma in altri punti sembra essere usato come un modo per definire un alias più breve.

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

3
Non ho idea (ancora) quello che persino dire, ma si può iniziare a scavare da qui: Magento\Framework\ObjectManager\Config\Mapper\Dom::convert. C'è una switchdichiarazione lì dentro da qualche parte.
Marius

Grazie @ Mario, mi chiedo anche se lessFileSourceBaseè limitato all'XML o se può essere utilizzato anche all'esterno. Suppongo che farò meglio a scavare.
David Manners,

Risposte:


84

I tipi virtuali sono un modo per iniettare dipendenze diverse nelle classi esistenti senza influenzare altre classi.

Ad esempio, la Magento\Framework\Session\Storageclasse accetta un $namespaceargomento nel suo costruttore, il cui valore predefinito è 'default', e puoi usare la typedefinizione per cambiare lo spazio dei nomi in 'core'.

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

La configurazione di cui sopra renderebbe in modo che tutte le istanze di Magento\Framework\Session\Storageabbiano uno spazio dei nomi di 'core'. L'uso di un tipo virtuale consente di creare l'equivalente di una sottoclasse, in cui solo la sottoclasse ha i valori degli argomenti modificati.

Nella base di codice vediamo le seguenti due configurazioni:

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

Il primo frammento crea un tipo virtuale per il Magento\Core\Model\Session\Storagequale altera lo spazio dei nomi e il secondo inserisce il tipo virtuale in Magento\Framework\Session\Generic. Ciò consente Magento\Framework\Session\Genericdi essere personalizzato senza influire su altre classi che dichiarano anche una dipendenzaMagento\Framework\Session\Storage


Grazie mille @Chris finalmente qualche giustificazione logica che ho trovato
Suman-PHP4U

È stata semplice e la migliore dimostrazione.
Umar,

Questa risposta è migliore del documento ufficiale di Magento
Suman-PHP4U il

<type>sta usando una classe virtuale che in realtà non esiste. In questo modo la modifica dell'argomento virtualTypeavrà effetto solo quando viene inizializzata la classe che utilizza virtualType, Magento\Framework\Session\Genericcome nell'esempio
Arif Ahmad

21

Un altro modo per comprendere i tipi virtuali:

Diciamo che hai una classe \Class1, che ha il seguente costruttore:

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

E \Class2ha il seguente costruttore -

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

Ora, vuoi cambiare il tipo di $argOfClass2da \Class3a \Class4, ma solo quando \Class2viene usato come $argOfClass1.

Il "vecchio" modo per farlo sarebbe quello di aggiungere quanto segue in di.xml-

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

dove \Class5è il seguente:

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

Invece di utilizzare in questo modo, è possibile utilizzare i tipi virtuali per ottenere lo stesso risultato, aggiungendo quanto segue a 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>

Come puoi vedere, usando il tipo virtuale hai salvato il lavoro di creazione di Class5.

Per ulteriore riferimento, suggerisco di leggere l'articolo di Alan Storm sui tipi virtuali in Magento2 - http://alanstorm.com/magento_2_object_manager_virtual_types/


1
buona espalinazione,
Anand Ontigeri il

Facile da capire. Grazie per aver condiviso un esempio di base.
Kalyan Chakravarthi V

10

Nello stesso di.xmlfile ho scoperto che lessFileSourceBaseviene passato come argomento per lessFileSourceBaseFilteredquello che viene passato come argomento per lessFileSourceBaseSortedche viene passato come argomento per il tipo Magento\Framework\Less\File\Collector\Aggregated.

Non ho trovato altra occorrenza di lessFileSourceBase(o lessFileSource) in un altro file se non di.xmldal modulo principale. Solo in alcuni file di cache, ma quelli non sono importanti.

Immagino che se non hai intenzione di usare il tipo virtuale in una classe PHP, ma solo nei difile xml non ti viene richiesto di farlo sembrare un nome di classe e puoi usare un alias.

Ma questa è solo pura speculazione.
Sarà "divertente" provare a creare una classe e iniettare nel suo costruttore un'istanza di lessFileSourceBasevedere come si comporta.


1
hai perso le virgolette intorno alla parola divertimento;)
David Manners,

1
@DavidManners. Destra. L'ho riparato. :)
Marius

@Marius: se si modifica \Magento\Framework\Session\Genericil file di origine in modo che dipenda Magento\Core\Model\Session\Storageinvece di StorageInterfacesi dovrebbe ottenere un'eccezione 'Classe Magento \ Core \ Model \ Session \ Storage non esiste'. Il motivo è che ObjectManager non crea un'istanza di virtualType, ma la utilizza solo per determinare quali argomenti fornire al costruttore del tipo concreto a cui fa riferimento la definizione di virtualType ( Magento\Framework\Session\Storageper l'esempio sopra).
Chris O'Toole,

Può vederlo in Factory , dove $requestedTyperappresenta il tipo virtuale e viene utilizzato per raccogliere gli argomenti, ma $typeè il tipo concreto a cui virtualType esegue il mapping e viene utilizzato per la chiamata di istanza dell'oggetto.
Chris O'Toole,

Quindi, anche se lessFileSourceBasefosse in uno stile più di tipo namespace \ class, non consentirebbe il riferimento diretto da un'altra classe php, solo per l'iniezione tramite il di.xml
Chris O'Toole,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.