Filtern der Produktsammlung nach einem anderen Attribut In der Produktsammlung, z. B. 'attribX', Array ('gt' => 'attrib-Y')

7

Bei Verwendung von Produktkollektionen wie folgt:

$_productCollection= Mage::getModel('catalog/product')->getCollection()
                    ->addAttributeToSelect('*')
                    ->addAttributeToFilter('special_price', array('neq'=>''));

Ist es möglich, addAttributeToFilter für ein Attribut relativ zu einem anderen Attribut zu verwenden? zB Kann ich special_price größer als price mit so etwas filtern

$_productCollection= Mage::getModel('catalog/product')->getCollection()
                    ->addAttributeToSelect('*')
                    ->addAttributeToFilter('special_price', array('gt'=>'price'));
James
quelle

Antworten:

4

Ich denke, Sie können dies mit erreichen addExpressionAttributeToSelect. Siehe Klasse Mage_Eav_Model_Entity_Collection_Abstractdazu. Sie können so etwas ausprobieren:

$_productCollection= Mage::getModel('catalog/product')->getCollection()
    ->addAttributeToSelect('*')
    ->addExpressionAttributeToSelect('difference', '(IF ({{special_price}} > {{price}} , 1, 0))', array('special_price', 'price'));

Dadurch wird differenceder Auswahl eine neue "Spalte" hinzugefügt , die den Wert 1 hat, wenn der Sonderpreis größer als der Preis ist. Jetzt müssen Sie nur noch nach dieser Spalte filtern.

$_productCollection->getSelect()->having('difference = ?', 1);
Marius
quelle
Gute, einfache Lösung, aber wenn Sie eine optimale Abfrageleistung benötigen, ist es besser, dies zu vermeidenHAVING
Fabian Schmengler
Ich denke nicht, dass es anders funktioniert
Marius
Meine Lösung ist weniger einfach, scheint aber zu funktionieren.
Fabian Schmengler
1

Sie können Zend_Db_ExprRaw-SQL anstelle von Werten verwenden. Bei Produktsammlungen müssen Sie jedoch vorsichtig sein, da die Abfrage anders ist, wenn der flache Produktindex aktiviert ist

EAV (Flat Index deaktiviert oder Admin-Bereich)

Hier brauchen wir auch einen Filter für das zweite Attribut hinzufügen , weil die Attribute werden ausgewählt wird in einer zweiten Abfrage geladen werden und Sie haben keinen Zugriff auf sie aus anderen Gründen . Wählen Sie etwas, das immer wahr ist. Ich habe mich für 'notnull' entschieden. Auf die verknüpfte Attributtabelle kann mit "at_" + Attributcode verwiesen werden:

$_productCollection
    ->addAttributeToFilter('price', ['notnull' => true])
    ->addAttributeToFilter(
        'special_price',
        ['lt' => new Zend_Db_Expr('at_price.value')]
    );

Verwenden des flachen Index

Mit dem Flat-Index können Sie direkt auf jedes Attribut zugreifen, das im Flat-Index enthalten ist (dh "In der Produktliste verwendet"):

$_productCollection->addAttributeToFilter(
    'special_price',
    ['lt' => new Zend_Db_Expr('price')]
);

Universelle Lösung

Mit addExpressionAttributeToSelect()@Marius können wir sicherstellen, dass alle im Ausdruck verwendeten Attribute verfügbar sind, ohne dass ein Dummy-Filter hinzugefügt werden muss (beide sind nur Problemumgehungen, funktionieren aber gleich gut). Dann müssen wir nur einen anderen Ausdruck verwenden, abhängig von isEnabledFlat():

$priceExpression = $_productCollection()->isEnabledFlat()
    ? new Zend_Db_Expr('price')
    : new Zend_Db_Expr('at_price.value');
$_productCollection
    ->addExpressionAttributeToSelect('difference', '(IF ({{special_price}} > {{price}} , 1, 0))', array('special_price', 'price'));
    ->addAttributeToFilter(
        'special_price',
        ['lt' => $priceExpression]
    );

Beachten Sie, dass wir differenceden Filter nicht verwenden , da er WHEREausgeführt wird, bevor der Wert berechnet wird. Dies bedeutet aber auch, dass MySQL die Abfrage besser optimieren kann als mit HAVING, das zuletzt ausgeführt wird.

Fabian Schmengler
quelle