Question

In short I seem unable to use a virtualType I created as an argument in my Action's contructor but everything works fine when using a concrete class instead.

Index.php (my action):

namespace Unit1\CustomConfig\Controller\Test;

use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Action\Action;
use Magento\Framework\Controller\ResultFactory;

class Index extends Action{
    private $customConfig;

    public function __construct(Context $context, \Unit1\CustomConfig\Model\Config $customConfig){
        $this->customConfig = $customConfig;
        return parent::__construct($context);
    }
}

My di.xml (Unit1/CustomConfig/etc/di.xml):

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager:etc/config.xsd">
    <virtualType name="Unit1\CustomConfig\Model\Config" type="Magento\Framework\Config\Data">
        <arguments>
            <argument name="reader" xsi:type="object">Unit1\CustomConfig\Model\Config\Reader</argument>
            <argument name="cacheId" xsi:type="string">welcome_messages</argument>
        </arguments>
    </virtualType>
    .......
</config>

I get the error:

main.CRITICAL: Class Unit1\CustomConfig\Model\Config does not exist

Class Unit1\CustomConfig\Controller\Test\Index\Interceptor generation error: The requested class did not generate properly, because the 'generated' directory permission is read-only. If --- after running the 'bin/magento setup:di:compile' CLI command when the 'generated' directory permission is set to write --- the requested class did not generate properly, then you must add the generated class object to the signature of the related construct method, only. [ ] [ ]

The error has nothing to do with file permissions (I checked and confirmed - it generates all the other files and folders - just not this interceptor as it cannot find the Model\Config class).

The thing is I am really confused on why it cannot find the virtualType or am I understanding the virtual type wrong?

This is part of an excercise in Magento U and the exercise initially used a concrete class for Model\Config along with a type (instead of virtualType) in the di.xml. I saw that the concrete class didn't really do much so based on my understanding of virtualType I wanted to confirm that I could simply replace it. But it's not so. How come? This was the original excercise solution which works:

Config.php:

namespace Unit1\CustomConfig\Model;

use Magento\Framework\Config\ReaderInterface;
use Magento\Framework\Config\CacheInterface;

class Config extends \Magento\Framework\Config\Data {
    public function __construct(ReaderInterface $reader, CacheInterface $cache, $cacheId = ''){
        parent::__construct($reader, $cache, $cacheId);
    }
}

and the corresponding type in the di.xml:

<type name="Unit1\CustomConfig\Model\Config">
    <arguments>
        <argument name="reader" xsi:type="object">Unit1\CustomConfig\Model\Config\Reader</argument>
        <argument name="cacheId" xsi:type="string">welcome_messages</argument>
    </arguments>
</type>

That is all that has changed - Instead of a concrete class and a type in di.xml I just turned it into a virtual type. And once I change those back they work perfectly. But the virtualType does not work. Can someone explain to my why?

Thanks!

Was it helpful?

Solution

According to magento docs:

Virtual types are a way to inject different dependencies into existing PHP classes without affecting other classes and without having to create a new class file. Virtual types can only be referenced in by argument overrides in a element within di.xml files, never in source code. They can't be extended and they can't be references as dependencies in a classes constructor. (magento glossary)

This is not the proper use. What you are trying to do is to use virtualType just like an interface when in fact those are two different concepts. virtualTypes are meant for di.xml manipulation only. They are usefull if you have Unit1\CustomConfig\Model\Config used in two or more classes as a dependency but ClassA needs to use Unit1\CustomConfig\Model\Config but replace one of its constructor arguments with a different value (for simple types) or a subclass (for classes).

Check this answer for more clarification.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top