How to override VirtualType block in Magento 2, I want to override following virtual type block with my own block,

<virtualType name="Magento\CatalogSearch\Block\SearchResult\ListProduct" type="Magento\Catalog\Block\Product\ListProduct">
       <argument name="catalogLayer" xsi:type="object">Magento\Catalog\Model\Layer\Search</argument>

So I tried to override it from my custom module di.xml like this,

<preference for="Magento\Catalog\Block\Product\ListProduct" type="My\Vendor\Block\Product\ListProductSearch" />

But it does not work.

So, what is the proper way of overriding a virtual type class in Magento 2?


You have to use:

<preference for="Magento\CatalogSearch\Block\SearchResult\ListProduct" type="Vendor\Module\Block\Product\ListProductSearch" />

as Raphael mentioned.

To make this singular block working properly, you need also to add view/frontend/layout/catalogsearch_result_index.xml file with following content:

<?xml version="1.0"?>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <referenceBlock name="search_result_list">
        <action method="setTemplate">
            <argument name="template" xsi:type="string">Magento_Catalog::product/list.phtml</argument>

  • 1
    Works like a charm! – Volvox Feb 6 '17 at 15:07
  • Why do you say you need the setTemplate action? I don't believe that's true. Setting a preference for the virtual type shouldn't affect the template setting that's already defined in the core layout XML. – Scott Buchanan Jul 6 '18 at 16:41
  • 1
    @ScottBuchanan as far as template provided contains module. When answering this question this block contained template as product/list.phtml so using preference changed template to Vendor_Module::product/list.phtml – Bartłomiej Szubert Jun 14 '19 at 10:18
  • Ah, makes sense. – Scott Buchanan Jun 14 '19 at 14:39

If you want to override the virtual type in your example, you need to use:

<preference for="Magento\CatalogSearch\Block\SearchResult\ListProduct" type="My\Vendor\Block\Product\ListProductSearch" />

Instead of:

<preference for="Magento\Catalog\Block\Product\ListProduct" type="My\Vendor\Block\Product\ListProductSearch" />

In your example, you override the original type and not the virtual type, that's the reason why it's not working.

  • Thank you for your answer, Now I have tried the way you mentioned, but it still doesn't work. – nuwaus Oct 24 '16 at 15:06
  • @nuwaus interesting, where is your di.xml located ? – Raphael at Digital Pianism Oct 24 '16 at 15:08
  • my-plugin-dir/etc/di.xml – nuwaus Oct 24 '16 at 15:12
  • @nuwaus what if you move it to etc/frontend/di.xml ? – Raphael at Digital Pianism Oct 24 '16 at 15:13
  • It still doesn't work :( – nuwaus Oct 24 '16 at 15:21

I'm not sure how exactly the xml configurations are merged and sorted, but this type of problem usually comes down to sequence of the modules being loaded.

I would try adding sequence to your module.xml :

        <module name="Magento_CatalogSearch"/>

The preference described by Raphael above is working fine for me.

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.