製品コレクションにフラットテーブルの代わりにEAVを使用させる


9

Magento 2でフラットカタログを一時的に無効にするにはどうすればよいですか?フロントエンドストアに関連付けられた製品コレクションがあり、EAVテーブルを介してそれをロードしたいと考えています。

コレクションがフラットテーブルを使用する必要があるかどうかをどのように判断するかを調べましたが、設定をどこにでも挿入する方法が見つかりませんでした。

Magento 1では、「フラットカタログが有効」の場合、読み込まれた構成値を変更していました。

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

このようなグローバルな状態に頼る必要がありますか?もしそうなら、どうですか?それとももっとエレガントな方法がありますか?

回答:


9

フラットインデックスが使用可能かどうかを判断するオブジェクト(クラスMagento\Catalog\Model\Indexer\Product\Flat\State)は、不変の共有インスタンスです。しかし、仮想タイプを使用して、独自のインスタンスを使用することは可能です。

これは私の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>

これで、仮想製品コレクションファクトリタイプができました。$isAvailable = false最終的には、独自の「State」インスタンスが使用されます。

disabledFlatStateProductCollectionFactory
 |
 + disabledFlatStateProductCollection
    |
    + disabledFlatState

また、フラットインデックスを無効にしたコレクションファクトリが必要なクラスでdisabledFlatStateProductCollectionFactoryは、対応するコンストラクターパラメーターの仮想型を指定します。

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

置換は、MagentoのDI実装が提供する最も強力なものです。良い解決策、私からの個人的な賛成票!
Ivan Chepurnyi 16年

これは私にはうまくいきません。:(カスタムクラスがある場合:public function __construct(\ Magento \ Catalog \ Model \ ResourceModel \ Product \ CollectionFactory $ collectionFactory){$ this-> _ collectionFactory = $ collectionFactory;}説明したdi.xmlを使用すると、 「Tは、Magentoのは、仮想タイプの代わりに、通常の製品のコレクションを使用していることがわかります。
mstojanov

6

製品コレクションがロードされるとき、それがEAVまたはフラットテーブルを使用するという事実は、この結果によって決定され\Magento\Catalog\Model\ResourceModel\Product\Collection::isEnabledFlat()ます。またはプラグイン
を記述して、特定のストアビューのコンテキスト内にいる場合に返すことができます。 aroundafterfalse

またはさらに良いことに、フラットフラグの値_flatEnabledは同じクラスのメンバーに格納(キャッシュ)されます。

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

メソッドに対して同じaroundまたはafterプラグインを記述できます\Magento\Catalog\Model\Indexer\Product\Flat\State::isAvailable()
このようにして、プラグインは一度だけ実行されます。その背後に重いロジックがある場合や、他の場所で使用されている場合に役立ちます。

これは、オンザフライで構成値を変更するよりもエレガントに見えます。


仮想タイプを使用して、カスタムコードなしで別のソリューションを見つけました。しかし、あなたのものが最も近くに来て、重要なヒントを与えたので、<del> kitkat </ del> <ins>奨励金</ ins>を
用意してください

後プラグインを書く方法は\Magento\Catalog\Model\Indexer\Product\Flat\State::isAvailable()
Liam Mitchell

1

よりエレガントな方法は、構成を保存するときにフラットモードを有効にするコードと同じコード使用することです。それは以下にあり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);
        }
    }
}

だから私はあなたがそのようなことをすることができると確信しています:

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

$this->_productFlatIndexerProcessorインスタンスはどこにありますか\Magento\Catalog\Model\Indexer\Product\Flat\Processor

可能な代替

ただし、そのメソッドは構成を保存しないため、システムが構成を介してフラットが有効になっているかどうかをシステムがチェックするときに、trueを返します。

可能な代替方法(テスト対象)はisFlatEnabledメソッドのプラグインMagento\Catalog\Model\Indexer\Product\Flat\State使用することです(メソッドは実際にはMagento\Catalog\Model\Indexer\AbstractFlatStateクラスで定義されています)。

達成したいことに基づいて、特定の条件下でそのメソッドがfalseを返すように後プラグインを設定できます。


確かsetScheduled(false)に、インデクサーの呼び出しは機能しません。これは、スケジュールされたインデックス作成を無効にするだけであり、コレクションに影響を与えないためです。しかし、とにかく、それはモードも保存します。これは間違いなく私が望むものではありません。
Fabian Schmengler、2016

@fschmenglerは完全に正しいです。フラットテーブルが有効かどうかをチェックするコードが構成を直接使用するためです。代替ソリューションはそれでもそれを克服します;)
Raphael at Digital Pianism
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.