type和virtualType有什么区别


41

di.xmlMagento2随附的中,有一个节点type和一个节点virtualType。我的问题是这是virtualType什么type?在什么情况下应使用它代替?

在某些地方,它看起来像是符号链接或重写:

<virtualType name="Magento\Core\Model\Session\Storage" type="Magento\Framework\Session\Storage">

一个完整的路径被更改为另一个完整的路径,而在其他地方,它似乎被用作定义较短别名的一种方式。

<virtualType name="lessFileSourceBase" type="Magento\Framework\View\File\Collector\Base">

3
我不知道(但)他们甚至意思,但你可以从这里开始挖掘:Magento\Framework\ObjectManager\Config\Mapper\Dom::convertswitch某处有一个声明。
马里乌斯

感谢@Marius,我也想知道是否lessFileSourceBase仅限于xml,或者是否也可以在外部使用。猜猜我最好去挖。
David Manners 2014年

Answers:


83

虚拟类型是一种将不同的依赖项注入现有类而不影响其他类的方法。

例如,Magento\Framework\Session\Storage该类$namespace在其构造函数中接受一个参数,该参数的默认值为“ default”,您可以使用该type定义将名称空间更改为“ core”。

<type name="Magento\Framework\Session\Storage">
    <arguments>
        <argument name="namespace" xsi:type="string">core</argument>
    </arguments>
</type>

上面的配置可以使所有实例Magento\Framework\Session\Storage具有“核心”名称空间。使用虚拟类型允许创建等效的子类,其中只有子类具有更改的参数值。

在代码库中,我们看到以下两个配置:

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

第一个代码段创建用于Magento\Core\Model\Session\Storage更改名称空间的虚拟类型,第二个代码段将该虚拟类型注入Magento\Framework\Session\Generic。这样Magento\Framework\Session\Generic就可以自定义,而不会影响其他也声明了依赖项的类Magento\Framework\Session\Storage


非常感谢@Chris我终于找到了一些合理的理由
Suman-PHP4U

那很简单,也是最好的示范。
Umar

这个答案是更好,然后Magento的官方文档
苏曼-PHP4U

<type>正在使用实际上不存在的虚拟类。这样,virtualType仅当初始化使用virtualType的类时,参数修改才会生效Magento\Framework\Session\Generic,在示例中
Arif Ahmad

21

了解虚拟类型的另一种方法-

假设您有一个类\Class1,它具有以下构造函数-

public function __construct(\Class2 $argOfClass1){...}

\Class2具有以下构造函数-

public function __construct(\Class3 $argOfClass2){...}

现在,您想要将的类型$argOfClass2从更改\Class3\Class4,但仅当\Class2用作时$argOfClass1

做到这一点的“旧”方法是在di.xml-中添加以下内容:

<type name="Class1">
    <arguments>
         <argument name="argOfClass1" xsi:type="object">Class5</argument>
    </arguments>
</type>

\Class5以下位置:

class \Class5 extends \Class2{
    public function __construct(\Class4 $argOfClass2){...}
}

除了使用这种方式,您还可以通过以下方式使用虚拟类型来实现相同目的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>

如您所见,使用虚拟类型可以节省创建的工作Class5

作为参考,我建议阅读Alan Storm关于Magento2中虚拟类型的文章-http : //alanstorm.com/magento_2_object_manager_virtual_types/


1
很好的解释,
Anand Ontigeri

容易理解。感谢您分享这样的基本示例。
Kalyan Chakravarthi V

10

在同一个di.xml文件中,我发现lessFileSourceBase用作参数lessFileSourceBaseFiltered传递,用作参数lessFileSourceBaseSorted传递类型Magento\Framework\Less\File\Collector\Aggregated

除了核心模块之外,我在其他文件中没有发现lessFileSourceBase(或lessFileSource)其他情况di.xml。仅在某些缓存文件中,但这些不重要。

我想如果您不打算在PHP类中使用虚拟类型,而只是在dixml文件中使用,则不需要使它看起来像类名,您可以使用别名。

但这仅仅是纯粹的猜测。
尝试创建一个类并将其实例注入其构造函数lessFileSourceBase以查看其行为将是一件“有趣的事情”。


1
您错过了围绕乐趣这个词的引号;)
David Manners 2014年

1
@DavidManners。对。我修好了它。:)
Marius

@Marius:如果您更改\Magento\Framework\Session\Generic源文件Magento\Core\Model\Session\Storage而不是依赖文件,StorageInterface则应获得“类Magento \ Core \ Model \ Session \ Storage不存在”的异常。原因是ObjectManager不会创建virtualType的实例,而只是使用它来确定为virtualType定义所引用的具体类型的构造函数提供哪些参数(Magento\Framework\Session\Storage对于上面的示例)。
克里斯·奥图尔

可以在Factory中看到这一点,其中$requestedType代表虚拟类型并用于收集参数,但是$typevirtualType映射到的具体类型并用于对象实例化调用。
克里斯·奥图尔

因此,即使lessFileSourceBase采用更命名空间\类类型的样式,也不允许其他php类直接引用,仅允许通过di.xml进行注入
Chris O'Toole
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.