Paksa pengumpulan produk untuk menggunakan EAV, bukan meja datar

9

Di Magento 2, bagaimana saya bisa menonaktifkan sementara katalog flat? Saya memiliki koleksi produk yang terkait dengan toko frontend dan ingin itu dimuat melalui tabel EAV.

Saya melihat bagaimana koleksi menentukan apakah tabel datar harus digunakan, tetapi tidak menemukan cara untuk menyuntikkan pengaturan di mana saja.

Di Magento 1 saya akan mengubah nilai konfigurasi yang dimuat untuk "katalog datar diaktifkan":

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

Apakah saya masih perlu menggunakan negara global seperti ini? Jika ya, bagaimana caranya? Atau ada cara yang lebih elegan?

Fabian Schmengler
sumber

Jawaban:

9

Objek yang bertanggung jawab untuk menentukan apakah indeks datar tersedia (kelas Magento\Catalog\Model\Indexer\Product\Flat\State) adalah instance bersama yang tidak dapat diubah. Tetapi dimungkinkan untuk menggunakan instance kita sendiri, menggunakan tipe virtual.

Ini milik saya 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>

Sekarang, saya memiliki jenis pabrik pengumpulan produk virtual, di mana contoh "State" saya sendiri $isAvailable = falsedigunakan akhirnya:

disabledFlatStateProductCollectionFactory
 |
 + disabledFlatStateProductCollection
    |
    + disabledFlatState

Dan untuk kelas di mana saya memerlukan pabrik pengumpulan dengan indeks datar dinonaktifkan, saya menentukan tipe virtual disabledFlatStateProductCollectionFactoryuntuk parameter konstruktor yang sesuai:

<arguments>
  <argument name="collectionFactory" xsi:type="object">disabledFlatStateProductCollectionFactory</argument>
</arguments>
Fabian Schmengler
sumber
Pergantian adalah hal yang paling kuat yang memberi Anda implementasi DI Magento! Solusi bagus, upvote pribadi dari saya!
Ivan Chepurnyi
Ini tidak berhasil untuk saya. :( Jika saya memiliki kelas khusus saya: fungsi publik __construct (\ Magento \ Katalog \ Model \ ResourceModel \ Product \ CollectionFactory $ collectionFactory) {$ this -> _ collectionFactory = $ collectionFactory;} Dengan di.xml seperti yang Anda jelaskan, saya tidak dapat melihat bahwa Magento menggunakan tipe virtual alih-alih pengumpulan produk reguler
mstojanov
6

Ketika koleksi produk dimuat, fakta bahwa ia menggunakan EAV atau tabel datar ditentukan oleh hasil ini \Magento\Catalog\Model\ResourceModel\Product\Collection::isEnabledFlat().
Anda dapat menulis aroundatau afterplugin, yang mengembalikan falsejika Anda berada dalam konteks tampilan toko tertentu.

Atau bahkan lebih baik, nilai untuk flag datar disimpan (di-cache) di anggota _flatEnableddari kelas yang sama.

public function isEnabledFlat()
{
    if (!isset($this->_flatEnabled[$this->getStoreId()])) {
        $this->_flatEnabled[$this->getStoreId()] = $this->getFlatState()->isAvailable();
    }
    return $this->_flatEnabled[$this->getStoreId()];
}

Anda dapat menulis plugin yang sama aroundatau afteruntuk metode ini \Magento\Catalog\Model\Indexer\Product\Flat\State::isAvailable().
Dengan cara ini plugin Anda dieksekusi hanya sekali. Ini bisa membantu jika Anda memiliki logika yang berat di baliknya atau jika digunakan di tempat lain.

Ini terlihat lebih elegan yang mengubah nilai konfigurasi dengan cepat.

Marius
sumber
Saya menemukan solusi berbeda tanpa kode khusus, menggunakan tipe virtual. Tetapi karena milik Anda datang paling dekat dan memberikan petunjuk penting, miliki <del> kitkat </del> <ins> karunia </ins>
Fabian Schmengler
Bagaimana cara menulis setelah plugin \Magento\Catalog\Model\Indexer\Product\Flat\State::isAvailable()?
Liam Mitchell
1

Cara yang lebih elegan adalah dengan menggunakan kode yang sama dengan kode yang memungkinkan mode flat saat menyimpan konfigurasi. Itu dapat ditemukan di bawah Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode:

public function processValue()
{
    if ((bool)$this->getValue() != (bool)$this->getOldValue()) {
        if ((bool)$this->getValue()) {
            $this->indexerState->loadByIndexer(\Magento\Catalog\Model\Indexer\Product\Flat\Processor::INDEXER_ID);
            $this->indexerState->setStatus(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID);
            $this->indexerState->save();
        } else {
            $this->_productFlatIndexerProcessor->getIndexer()->setScheduled(false);
        }
    }
}

Jadi saya cukup yakin Anda bisa melakukan hal seperti itu:

$this->_productFlatIndexerProcessor->getIndexer()->setScheduled(false);

Di mana $this->_productFlatIndexerProcessoradalah contoh dari \Magento\Catalog\Model\Indexer\Product\Flat\Processor.

Alternatif yang mungkin

Namun, metode itu tidak menyimpan konfigurasi sehingga ketika sistem memeriksa apakah flat diaktifkan melalui konfigurasi itu masih mengembalikan true.

Alternatif yang mungkin (untuk diuji) adalah menggunakan plugin pada isFlatEnabledmetode dariMagento\Catalog\Model\Indexer\Product\Flat\State (metode ini sebenarnya didefinisikan di Magento\Catalog\Model\Indexer\AbstractFlatStatekelas).

Berdasarkan apa yang ingin Anda capai, Anda dapat menyiapkan plugin setelah untuk memaksa metode itu untuk mengembalikan false dalam kondisi tertentu.

Raphael di Digital Pianism
sumber
Saya cukup yakin, memanggil setScheduled(false)pengindeks tidak berfungsi karena hanya menonaktifkan pengindeksan terjadwal dan tidak akan berdampak pada koleksi. Tapi bagaimanapun, ini juga menyimpan mode, yang jelas bukan yang saya inginkan.
Fabian Schmengler
@fschmengler sepenuhnya benar, terutama karena kode yang memeriksa apakah tabel datar diaktifkan menggunakan konfigurasi secara langsung. Solusi alternatif akan mengatasi itu;)
Raphael di Digital Pianism