What is the difference between type and virtualType
Virtual types are a way to inject different dependencies into existing classes without affecting other classes.
For example, the Magento\Framework\Session\Storage
class takes a $namespace
argument in its constructor, which defaults to the value 'default', and you could use the type
definition to change the namespace to 'core'.
<type name="Magento\Framework\Session\Storage">
<arguments>
<argument name="namespace" xsi:type="string">core</argument>
</arguments>
</type>
The above config would make it so that all instances of Magento\Framework\Session\Storage
have a namespace of 'core'. Using a virtual type allows for the equivalent of a sub-class to be created, where only the sub-class has the altered argument values.
In the codebase we see the following two configurations:
<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>
The first snippet creates a virtual type for Magento\Core\Model\Session\Storage
which alters the namespace, and the second inject the virtual type into Magento\Framework\Session\Generic
. This allows Magento\Framework\Session\Generic
to be customized without affecting other classes that also declare a dependency on Magento\Framework\Session\Storage
Another way to understand virtual types -
Let's say that you have a class \Class1
, which has the following constructor -
public function __construct(\Class2 $argOfClass1){...}
And \Class2
has the following constructor -
public function __construct(\Class3 $argOfClass2){...}
Now, you want to change the type of $argOfClass2
from \Class3
to \Class4
, but only when \Class2
is used as $argOfClass1
.
The "old" way to do that would be to add the following in di.xml
-
<type name="Class1">
<arguments>
<argument name="argOfClass1" xsi:type="object">Class5</argument>
</arguments>
</type>
where \Class5
is the following:
class \Class5 extends \Class2{
public function __construct(\Class4 $argOfClass2){...}
}
Instead of using this way, you can use the virtual types to accomplish the same, by adding the following to 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>
As you can see, using the virtual type saved you the work of creation of Class5
.
For further reference I suggest to read Alan Storm's article regarding virtual types in Magento2 - http://alanstorm.com/magento_2_object_manager_virtual_types/
In the same di.xml
file I found that lessFileSourceBase
is passed as an argument for lessFileSourceBaseFiltered
that is passed as an argument for lessFileSourceBaseSorted
that is passed as an argument for type Magento\Framework\Less\File\Collector\Aggregated
.
I found no other occurrence of lessFileSourceBase
(or lessFileSource
) in an other file except di.xml
from the core module. Only in some cache files but those are not important.
I guess if you are not going to use the virtual type in a PHP class, but only in the di
xml files then you are not required to make it look like a class name and you can use an alias.
But this is just pure speculation.
It will be "fun" to try to create a class and inject in its constructor an instance of lessFileSourceBase
to see how it behaves.