0

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:

    1. <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 by name=, (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?
    2. Is this how you would use type and virtualType.... 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 main xsi:type=object referenced somewhere, then using virtualTypes I call them using the name?

    3. Do I do this (based on instance1 or instance2 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)

2
  • <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)

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

  • Thank you :) Your last XML comments made it absolutely clear, the word 'merge' is the key here. Thanks for advice! – CvRChameleon Jun 3 '20 at 7:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.