Magento 2 – Force Products Collection to Use EAV Instead of Flat Table

collection;flat-catalogmagento-2.1magento2product-collection

In Magento 2, how can I temporarily disable the flat catalog? I have a product collection associated with a frontend store and want it to be loaded via EAV tables.

I looked how the collections determine if flat tables should be used, but did not find a way to inject the setting anywhere.

In Magento 1 I would have changed the loaded configuration value for "flat catalog enabled":

Mage::app()->getStore($storeId)->setConfig('catalog/frontend/flat_catalog_product', 0);

Do I still need to resort to global state like this? If so, how? Or is there a more elegant way?

Best Answer

The object which is responsible to determine if flat index is available (class Magento\Catalog\Model\Indexer\Product\Flat\State) is an immutable shared instance. But it is possible to use our own instance, using virtual types.

This is my di.xml:

  <virtualType name="disabledFlatStateProductCollectionFactory" type="Magento\Catalog\Model\ResourceModel\Product\CollectionFactory">
    <arguments>
      <argument name="instanceName" xsi:type="string">disabledFlatStateProductCollection</argument>
    </arguments>
  </virtualType>
  <virtualType name="disabledFlatStateProductCollection" type="Magento\Catalog\Model\ResourceModel\Product\Collection">
    <arguments>
      <argument name="catalogProductFlatState" xsi:type="object">disabledFlatState</argument>
    </arguments>
  </virtualType>
  <virtualType name="disabledFlatState" type="Magento\Catalog\Model\Indexer\Product\Flat\State">
    <arguments>
      <argument name="isAvailable" xsi:type="boolean">false</argument>
    </arguments>
  </virtualType>

Now, I have a virtual product collection factory type, where my own "State" instance with $isAvailable = false is used eventually:

disabledFlatStateProductCollectionFactory
 |
 + disabledFlatStateProductCollection
    |
    + disabledFlatState

And for the classes where I need a collection factory with disabled flat index, I specify the virtual type disabledFlatStateProductCollectionFactory for the corresponding constructor parameter:

<arguments>
  <argument name="collectionFactory" xsi:type="object">disabledFlatStateProductCollectionFactory</argument>
</arguments>
Related Topic