Forza la raccolta di prodotti a utilizzare EAV invece di un tavolo piano


9

In Magento 2, come posso disabilitare temporaneamente il catalogo flat? Ho una collezione di prodotti associata a un negozio frontend e voglio che sia caricata tramite tabelle EAV.

Ho osservato come le raccolte determinano se utilizzare le tabelle piane, ma non ho trovato il modo di iniettare l'impostazione da nessuna parte.

In Magento 1 avrei modificato il valore di configurazione caricato per "catalogo flat abilitato":

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

Devo ancora ricorrere a uno stato globale come questo? Se é cosi, come? O c'è un modo più elegante?

Risposte:


9

L'oggetto responsabile di determinare se è disponibile l'indice flat (classe Magento\Catalog\Model\Indexer\Product\Flat\State) è un'istanza condivisa immutabile. Ma è possibile usare la nostra propria istanza, usando tipi virtuali.

Questo è il mio 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>

Ora, ho un tipo di factory di raccolta prodotti virtuale, dove $isAvailable = falsealla fine viene utilizzata la mia istanza "State" con :

disabledFlatStateProductCollectionFactory
 |
 + disabledFlatStateProductCollection
    |
    + disabledFlatState

E per le classi in cui ho bisogno di una factory di raccolta con indice piatto disabilitato, specifica il tipo virtuale disabledFlatStateProductCollectionFactoryper il parametro costruttore corrispondente:

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

La sostituzione è la cosa più potente che ti offre l'implementazione DI di Magento! Buona soluzione, voto personale da parte mia!
Ivan Chepurnyi,

Questo non funziona per me. :( Se ho la mia classe personalizzata: funzione pubblica __construct (\ Magento \ Catalog \ Model \ ResourceModel \ Product \ CollectionFactory $ collectionFactory) {$ this -> _ collectionFactory = $ collectionFactory;} Con il di.xml come hai spiegato, io don vedi che Magento utilizza il tipo virtuale invece della normale raccolta di prodotti.
mstojanov

6

Quando viene caricata una raccolta di prodotti, il risultato che utilizza EAV o tabelle piatte è determinato da questo risultato \Magento\Catalog\Model\ResourceModel\Product\Collection::isEnabledFlat().
È possibile scrivere un plug-in aroundo after, che ritorna falsese ci si trova nel contesto di una determinata vista dello store.

O ancora meglio, i valori per flat flag sono memorizzati (memorizzati nella cache) nel membro _flatEnableddella stessa classe.

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

Puoi scrivere lo stesso aroundo afterplugin per il metodo \Magento\Catalog\Model\Indexer\Product\Flat\State::isAvailable().
In questo modo il tuo plugin viene eseguito solo una volta. Potrebbe essere utile se hai dietro una logica pesante o se viene utilizzato in altri luoghi.

Sembra più elegante che cambiare al volo un valore di configurazione.


Ho trovato una soluzione diversa senza alcun codice personalizzato, utilizzando tipi virtuali. Ma poiché il tuo si avvicina di più e ti ha dato un suggerimento importante, prendi un <del> kitkat </del> <ins> generosità </ins>
Fabian Schmengler,

Come scrivere un after plugin per \Magento\Catalog\Model\Indexer\Product\Flat\State::isAvailable()?
Liam Mitchell,

1

Il modo più elegante sarebbe usare lo stesso codice del codice che abilita la modalità flat quando si salva la configurazione. Si può trovare sotto 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);
        }
    }
}

Quindi sono abbastanza sicuro che potresti fare qualcosa del genere:

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

Dov'è $this->_productFlatIndexerProcessorun'istanza di \Magento\Catalog\Model\Indexer\Product\Flat\Processor.

Alternativa possibile

Tuttavia, quel metodo non salva la configurazione, quindi quando il sistema controlla se flat è abilitato tramite la configurazione, ritorna comunque vero.

Una possibile alternativa (da testare) sarebbe quella di utilizzare un plugin sul isFlatEnabledmetodo daMagento\Catalog\Model\Indexer\Product\Flat\State (il metodo è attualmente definito nella Magento\Catalog\Model\Indexer\AbstractFlatStateclasse).

In base a ciò che si desidera ottenere, è possibile impostare un plug-in successivo per forzare tale metodo a restituire false in determinate condizioni.


Sono abbastanza sicuro, chiamare setScheduled(false)l'indicizzatore non funziona perché disabilita solo l'indicizzazione pianificata e non avrà alcun impatto sulle raccolte. Ma a prescindere, salva anche la modalità, che sicuramente non è quello che voglio.
Fabian Schmengler,

@fschmengler ha perfettamente ragione, specialmente perché il codice che controlla se la tabella piatta è abilitata usa direttamente la configurazione. La soluzione alternativa lo supererà però;)
Raffaello al Pianismo digitale,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.