Dependency Injection (di.xml) - (virtualType vs type) Magento 2 xsi:type='object'
-
14-04-2021 - |
Question
Can someone please explain when you would use <type/>
or <virtualType
in your di.xml
file?
I want to make sure I understand it correctly..
At the moment, this is what I sort of think the difference is, especially with xsi:type='object'
as arguments.
Type:
<type name='Some\File\Object'>
<arguments>
<argument name="someText" xsi:type="string">String Value for This Arg</argument>
<argument name="someArg" xsi:type="object">Some\Object\Arg\For\This\Arg</argument>
</arguments>
</type>
Virtual Type:
<virtualType name='instance1' type='Some\File\Object'>
<arguments>
<argument name="someArg" xsi:type="object">Some\Object\Arg\For\This\Arg</argument>
</arguments>
</virtualType>
<virtualType name='instance2' type='Some\File\Object'>
<arguments>
<argument name="someArg" xsi:type="object">Some\Other\Object\Arg\For\This\Arg</argument>
</arguments>
</virtualType>
So the questions I guess: - This is what I think it does:
<type/> vs </virtualType>
usage:<type/>
: This is a singular instance, and everywhere Magento 2 references this type, would it replace the argument given for every other class that use this object (argument)?<virtualType/>
: These ones you are able to call byname=
, (in my example instance1, or instance2) to differentiate their usage at different places. I then call them and give them different argument values, so they do not interact with each other?
Is this how you would use
type
andvirtualType
.... one/more objects and then 'override' them for use in other places that do not have any dependency on each other. For example: creating different log files, Magento has the mainxsi:type=object
referenced somewhere, then using virtualTypes I call them using thename
?Do I do this (based on
instance1
orinstance2
above) example usage:
Use Type
<type name='Some\Other\ObjectB'>
<arguments>
<argument name="ObjectInstance" xsi:type='object'>instance1</argument>
</arguments>
</type>
<type name='Some\Other\ObjectB'>
<arguments>
<argument name="ObjectInstance" xsi:type='object'>instance2</argument>
</arguments>
</type>
OR VirtualType:
<virtualType name='Some\Other\ObjectB'>
<arguments>
<argument name="ObjectInstance" xsi:type='object'>instance1</argument>
</arguments>
</virtualType>
<virtualType name='Some\Other\ObjectB'>
<arguments>
<argument name="ObjectInstance" xsi:type='object'>instance2</argument>
</arguments>
</virtualType>
I think the confusion is when do I use <virtualType/>
elements do I use them in conjunction with AND / OR , especially when I want to use multiple virtualTypes with just arguments different (log files for sake of this discussion)
Solution
<preferance>
- is directive for mapping type to interface<type>
- is directive for configure concrete type<virtualType>
- is directive for create alias for type
Example:
class A {
function __construct(
AInt $a,
BInt $b
)
}
You can not create such class, because it contains link to Interfaces So you can map interfaces to implementation
preference AInt => AClass, BInt => BClass
so it will work like you define class A like
class A {
function __construct(
AInt $a,
BInt $b
)
}
but lest imagine that some subsystems require class A initiated in different way.
You can do it with defining Class D like
class D extends A {
function __construct(
AInt $a,
EClass $b
)
}
or define virtualType
D.
So, to answer on your question:
1.1 Yes, it will update type of argument for all instances and subtypes
1.2 Yes, virtualType
update type of argument only for self (or other virtual types based on this)
- Yes, type configuration is global, you need use
virtualType
to overwrite for subsystem
<type name='Some\Other\ObjectB'>
<arguments>
<argument name="ObjectInstance" xsi:type='object'>instance1</argument>
</arguments>
</type>
<type name='Some\Other\ObjectB'>
<arguments>
<argument name="ObjectInstance" xsi:type='object'>instance2</argument>
</arguments>
</type>
is the same as
<type name='Some\Other\ObjectB'>
<arguments>
<argument name="ObjectInstance" xsi:type='object'>instance2</argument>
</arguments>
</type>
Magento merges all declarations with same name, so you need use virtualType
here