Filtern Sie die Produktsammlung nach nicht flachen Attributen

14

Ich mache folgendes:

$productCollection = Mage::getModel('catalog/product')
    ->getCollection();

$productCollection
    ->addAttributeToFilter('my_attribute', 1);

my_attribute ist nicht in den flachen Tabellen, aber flache Tabellen sind aktiviert.

Ich bekomme immer die volle Sammlung.

Der Grund scheint zu sein in \Mage_Catalog_Model_Resource_Product_Collection::addAttributeToSelect:

$columns = $this->getEntity()->getAttributeForSelect($attributeCode);

No $this->getEntity()ist eine Instanz, Mage_Catalog_Model_Resource_Product_Flatdie die flachen Felder abruft. Wenn keine gefunden wird, wird nur null zurückgegeben.

Was ist eine saubere Methode, um dem Sammlungsfilter ein nicht flaches Attribut hinzuzufügen?

In meinem Fall macht es keinen Sinn, das Attribut der flachen Tabelle hinzuzufügen.

Alex
quelle
Hallo Sir, sind Sie freundlich genug, um Verwirrung zu lösen? WAT ist gemeint mit non-flat attribute? Danke .und mach Magento nicht verwirrend. Es ist bereits verwirrend
Pratik
Ich spreche von Attributen, die nicht im Flat-Index enthalten sind. In diesen Fällen ist "Verwendet in Produktliste" auf "Nein" gesetzt.
Alex

Antworten:

18

Sie könnten sich selbst an den nötigen Tisch setzen.

$productCollection = Mage::getModel('catalog/product')
->getCollection();

$table = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'my_attribute')->getBackend()->getTable();
$attributeId = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'my_attribute')->getAttributeId();

$productCollection->getSelect()->join(array('attributeTable' => $table), 'e.entity_id = attributeTable.entity_id', array('my_attribute' => 'attributeTable.value'))
                            ->where("attributeTable.attribute_id = ?", $attributeId)
                            ->where("attributeTable.value = ?", 1);

Vielleicht möchten Sie auch store_id beitreten.

Matthias Zeis
quelle
Ich glaube ich hätte immer noch das Problem, dass ich nicht die Produkte aller Läden bekomme. (Wann immer ich dieses Problem ursprünglich nicht in meiner Frage gesehen habe). Es sieht so aus, als ob ich die flachen Indizes vollständig deaktivieren möchte.
Alex
Wenn Sie alle Produkte benötigen, sind flache Tische nicht Ihre Freunde, ja.
Matthias Zeis
Dann möchten Sie vielleicht Ihre Frage ändern oder meine Antwort akzeptieren (die für die ursprüngliche Frage funktioniert).
Matthias Zeis
awasome .. concept
Amit Bera
15

Ein Hack (CE 1.6.2.0+) besteht darin, die Bedingung als Array zu übergeben und zu glauben, dass dies wie beabsichtigt funktioniert oder nicht:

$collection->addFieldToFilter(array(array('attribute' => 'my_attribute', 'eq' => 1)));
ColinM
quelle
Irgendeine Ahnung, warum das funktioniert?
Alex
3
Dies funktioniert, weil eav collection addFieldToFilerein Wrapper für ist addAttributeToFilterund dieses Attribut optional als Array übergeben werden kann:if (is_array($attribute)) { $sqlArr = array(); foreach ($attribute as $condition) { $sqlArr[] = $this->_getAttributeConditionSql($condition['attribute'], $condition, $joinType); } $conditionSql = '('.implode(') OR (', $sqlArr).')'; }
Marius
@Marius, heißt das, es ist kein Hack? : P Kann ich mich gut fühlen, wenn ich es benutze?
Erfan
3
@Erfan. Es ist kein Hack. Es ist ein Feature.
Marius
Süss. Es ist immer noch seltsam, dass die Produkttabellenimplementierung (eav / flat) nicht so einfach wie das Filtern einer Sammlung abstrahiert wird. Bedeutet dies, dass ich in meinem Code immer addFieldToFilter anstelle von addAttributeToFilter verwenden muss, da ich nicht weiß, ob eav oder flat verwendet wird? Wozu eigentlich addAttributeToFilter?
Erfan
6

Der Grund, warum die Antwort von ColinM funktioniert, liegt in der Code-in app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php- addAttributeToFilterMethode. Wenn Sie dieses Array-Format verwenden, wird es nicht aufgerufen addAttributeToSelect. Im Flat-Modus addAttributeToSelectschlägt die automatische Ausführung fehl, wenn das Attribut nicht in der Flat-Tabelle enthalten ist.

(unten ist ein erneuter Hash meiner Antwort auf /programming/6271284/can-i-add-other-attributes-to-magentos-flat-product-catalog-table/17021620 - I'm Ich bin mir nicht sicher, wie die Etikette dafür aussieht, aber ich weiß, ich hätte es hilfreich gefunden.

Ich wollte eine "saubere" Lösung für die Auswahl und Filterung von Flat-Mode-Sammlungen nach nicht-Flat-Attributen, die:

  • erfordert keine spezifischen Einstellungen für das Attribut in admin (möglicherweise von einem Benutzer hinzugefügt oder im Front-End ausgeblendet)
  • Funktioniert sowohl für den Flat- als auch für den Non-Flat-Modus

Ich habe die zugehörige Produktsammlung verwendet, dies gilt jedoch für alle EAV-Sammlungen.

Fehlercode:

$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
    ->addAttributeToSelect( 'my_custom_attribute' )
    ->addAttributeToFilter( 'my_custom_attribute', 3 )
;

Im Flat-Modus kann der obige Code das Attribut nicht automatisch auswählen oder filtern, wenn es sich nicht in der Flat-Tabelle befindet.

Hinzufügen zur Auswahl:

$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
    ->joinAttribute( 'my_custom_attribute', 'catalog_product/my_custom_attribute', 'entity_id', null, 'left' )
    ->addAttributeToSelect( 'my_custom_attribute' )
;

Die joinAttributeMethode fügt der Abfrage einen Join für das angeforderte Attribut hinzu. Es funktioniert immer noch, wenn sich das Attribut bereits in der flachen Tabelle befindet, ist jedoch etwas weniger effizient als die reine Verwendung der flachen Tabelle.

Ich habe dort einen leftJoin verwendet, um sicherzustellen, dass Produkte my_custom_attributeabgerufen werden, wenn dieser nicht für diese Produkte festgelegt ist. Ändern Sie dies, innerwenn Sie nur an Zeilen interessiert sind, in denen festgelegt my_custom_attributeist.

Hinzufügen zum Filter (gemäß obigem ColinM):

$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
    ->addAttributeToFilter( array( array( 'attribute' => 'my_custom_attribute', 'eq' => 3 ) ) )
;

Der obige Code fügt ihn der Auswahl hinzu und folgt Ihrem Filter.

(getestet in CE 1.6.2.0)

Johnorourke
quelle
4

In dem Mage_RssModul verwendete sie das ein hacky-Verfahren der flachen Tabellen zu deaktivieren. Sie nutzen die Tatsache, dass flache Tabellen im Admin-Store immer deaktiviert sind und emulieren daher einfach den Admin-Store.

class Mage_Rss_Helper_Data {

[...]

/**
 * Disable using of flat catalog and/or product model to prevent limiting results to single store. Probably won't
 * work inside a controller.
 *
 * @return null
 */
public function disableFlat()
{
    /* @var $flatHelper Mage_Catalog_Helper_Product_Flat */
    $flatHelper = Mage::helper('catalog/product_flat');
    if ($flatHelper->isEnabled()) {
        /* @var $emulationModel Mage_Core_Model_App_Emulation */
        $emulationModel = Mage::getModel('core/app_emulation');
        // Emulate admin environment to disable using flat model - otherwise we won't get global stats
        // for all stores
        $emulationModel->startEnvironmentEmulation(0, Mage_Core_Model_App_Area::AREA_ADMINHTML);
    }
}

Nach dem Start der Emulation sollten Sie diese mit zurücksetzen emulationModel->stopEnvironmentEmulation()

Alex
quelle
Wo war diese Antwort vor 3 Tagen? ; _;
SG3S
Genau hier? Seit dem 20. März
Alex
1

Wenn Sie das Attribut erstellen, sollte es auf globaler Ebene und filterbar sein. Auf diese Weise kann es in der Layared Navigation verwendet werden. Außerdem muss das Attribut Dropdown oder Mehrfachauswahl sein. Ich würde persönlich davon abraten, die Kerndateien in diesem Fall an Ihre Bedürfnisse anzupassen

Sander Mangel
quelle
Ich möchte das Attribut nicht im Frontend-Filter haben, sondern nur eine Sammlungsfilterung für den internen Gebrauch.
Alex