1

For example, anybody can modify this virtual type magento/module-catalog/etc/di.xml:

<virtualType name="Magento\Catalog\Model\Layer\Search\Context" type="Magento\Catalog\Model\Layer\Context">
    <arguments>
        <argument name="collectionProvider" xsi:type="object">Magento\Catalog\Model\Layer\Search\ItemCollectionProvider</argument>
        <argument name="stateKey" xsi:type="object">Magento\Catalog\Model\Layer\Category\StateKey</argument>
        <argument name="collectionFilter" xsi:type="object">Magento\Catalog\Model\Layer\Search\CollectionFilter</argument>
    </arguments>
</virtualType>

Let's assume that instead

Magento\Catalog\Model\Layer\Search\ItemCollectionProvider  

now

Vendor\Name\Model\Layer\Search\ItemCollectionProvider

When I implement virtual type (Magento\Catalog\Model\Layer\Search\Context) in own class constructor I get fatal error:

Class Magento\Catalog\Model\Layer\Search\Context does not exist

It seems, that using of virtual types is allowed only in di.xml

I can inject in own class the class which use this context, but context is the protected property and i can't get it.

How I can find class Vendor\Name\Model\Layer\Search\ItemCollectionProvider from any place of code?

4

The configurations declared via virtualType are not sub-classes of base class.

Virtual types with class-similar names add some confusion in this problem.

You need to perceive "virtual types" as configured instances of base class.

Example:

di.xml

<virtualType name="LetterA" type="Magento\Framework\Alphabet\CharacterInterface">
    <arguments>
        <argument name="symbol" xsi:type="string">A</argument>
    </arguments>
</virtualType>
<virtualType name="LetterB" type="Magento\Framework\Alphabet\CharacterInterface">
    <arguments>
        <argument name="symbol" xsi:type="string">B</argument>
    </arguments>
</virtualType>

<type name="Magento\Framework\Alphabet\CharacterListInterface">
    <arguments>
        <argument name="characters" xsi:type="array">
            <item name="a" xsi:type="object">LetterA</item>
            <item name="b" xsi:type="object">LetterB</item>
        </argument>
    </arguments>
</type>

This configuration in PHP code without DI looks like:

$a = new Character('A');
$b = new Character('B');

$list = new CharacterList([
    'a' => $a,
    'b' => $b
]);

Pay attention to this - only class instances, without subtypes of Character.


In your case, if you need to inject virtual types object in your constructor, you need to inject the virtual type's base type and add type-preference to di.xml special for your class.

Example:

MyClass.php

class MyClass
{
    /**
     * @param \Magento\Catalog\Model\Layer\Context $context
     */
    public function __construct(\Magento\Catalog\Model\Layer\Context $context)
    {
        $this->context = $context;
    }
}

di.xml

<type name="Vendor\Name\Model\MyClass">
    <arguments>
        <argument name="context" xsi:type="object">Magento\Catalog\Model\Layer\Search\Context</argument>
    </arguments>
</type>

So the virtual type will be injected in your class.

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.