Virtual types

Virtual types are a very neat feature of Magento that allow us to change the arguments of a specific injectable dependency and thus change the behavior of a particular class type.

The <MAGENTO_DIR>/module-checkout/etc/di.xml file provides a simple example of virtualType and its usage:

<virtualType name="MagentoCheckoutModelSessionStorage" type="MagentoFrameworkSessionStorage">
<arguments>
<argument name="namespace" xsi:type="string">checkout</argument>
</arguments>
</virtualType>
<type name="MagentoCheckoutModelSession">
<arguments>
<argument name="storage" xsi:type="object">MagentoCheckoutModelSessionStorage</argument>
</arguments>
</type>

The virtualType here (virtually) extends MagentoFrameworkSessionStorage by rewriting its constructor's $namespace = 'default' argument to $namespace = 'checkout'. However, this change does not kick in on its own, as the MagentoCheckoutModelSessionStorage virtual type must be used first. It is used in this case, via a type definition, where the storage argument is replaced entirely by the virtual type.

Most of the virtualType name attributes across Magento take the form of a non-existing fully qualified class name, though this can be any character combination that's allowed in PHP array keys.

By doing a lookup for the <virtualType string across the entire <MAGENTO_DIR> directory's di.xml files, we can see that Magento uses hundreds of virtual types across the majority of its modules.

A more complex example of virtual type usage can be found under the Magento_LayeredNavigation module.

The <MAGENTO_DIR>/module-layered-navigation/etc/frontend/di.xml file defines two virtual types, as follows:

<virtualType name="MagentoLayeredNavigationBlockNavigationCategory" type="MagentoLayeredNavigationBlockNavigation">
<arguments>
<argument name="filterList" xsi:type="object">categoryFilterList</argument>
</arguments>
</virtualType>

<virtualType name="MagentoLayeredNavigationBlockNavigationSearch" type="MagentoLayeredNavigationBlockNavigation">
<arguments>
<argument name="filterList" xsi:type="object">searchFilterList</argument>
</arguments>
</virtualType>

Here, we have two virtual types defined, each changing the filterList argument of the MagentoLayeredNavigationBlockNavigation class. categoryFilterList and searchFilterList are the names of two other virtual types that are defined in <MAGENTO_DIR>/module-catalog-search/etc/di.xml, as visible here: https://github.com/magento/magento2/blob/2.2/app/code/Magento/CatalogSearch/etc/di.xml.

The MagentoLayeredNavigationBlockNavigationCategory and MagentoLayeredNavigationBlockNavigationSearch virtual types are then used in layout files for block definition, as follows:

<!-- view/frontend/layout/catalog_category_view_type_layered.xml -->
<referenceContainer name="sidebar.main">
<block class="MagentoLayeredNavigationBlockNavigationCategory" ...
</referenceContainer>

<!-- view/frontend/layout/catalogsearch_result_index.xml -->
<referenceContainer name="sidebar.main">
<block class="MagentoLayeredNavigationBlockNavigationSearch" ...
</referenceContainer>

What this effectively does is tell Magento that, for the category view page and search page, use the virtual type for class, thus instructing it to go through all the argument changes specified in the virtual type.

This is an interesting example as it reveals the potential complexity of using virtual types. Basically, we have one virtual type (MagentoLayeredNavigationBlockNavigationSearch) changing the single filterList argument of a real type (MagentoLayeredNavigationBlockNavigation) with another virtual type (categoryFilterList). Likewise, we just learned how the class property of the block element is capable of not just accepting the fully qualified class name, but the virtualType name as well.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.221.113