Magento Extension Single Configurable Products

Mit der Magento Extension "Simple Configurable Products" von Organic Internet sollte es möglich sein, in der Artikelliste (innerhalb einer Kategorie) den niedrigsten Preis für ein konfigurierbares Produkt in Abhängigkeit von den zugeordneten einfachen Produkten anzeigen zu lassen. Es soll somit der niedrigste Preis aller zugeordneten Produkte angezeigt werden. Die SCP-Extension führt hierzu (überwiegend) geeignete Datenankabfragen durch, in den Sie mit der ORDER-Anweisung die gewünschten Zeilen anfordert.

Funktioniert jedoch nur solange, bis man auf das Datenbankverwaltungsverwaltungssytem MariaDB zugreifen möchte, so wie aktuell in den Managed Server Paketen von Strato zur Verfügung gestellt und von Magento-Verwendern gerne verwendet. Ein Blick auf die von SCP verwendete Abfrage bringt dann hervor (siehe in app /code /community /OrganicInternet /SimpleConfigurableProducts /Catalog /Model /Resource /Eav /Mysql4 /Product /Indexer /Price /Configurable.php):

 

INSERT INTO 'catalog_product_index_price_final_idx' SELECT 'inner'.'entity_id', 'inner'.'customer_group_id', 'inner'.'website_id', 'inner'.'tax_class_id', 'inner'.'orig_price', 'inner'.'price', 'inner'.'min_price', MAX(inner.max_price) AS 'max_price', 'inner'.'tier_price', 'inner'.'base_tier', 'inner'.'group_price', 'inner'.'base_group_price' FROM (SELECT e.entity_id AS 'entity_id', pi.customer_group_id AS 'customer_group_id', cw.website_id AS 'website_id', pi.tax_class_id AS 'tax_class_id', pi.price AS 'orig_price', pi.final_price AS 'price', pi.final_price AS 'min_price', pi.final_price AS 'max_price', pi.tier_price AS 'tier_price', pi.tier_price AS 'base_tier', pi.tier_price AS 'group_price', pi.tier_price AS 'base_group_price' FROM 'catalog_product_entity' AS 'e'
LEFT JOIN 'catalog_product_super_link' AS 'l' ON l.parent_id = e.entity_id
INNER JOIN 'catalog_product_entity' AS 'ce' ON ce.entity_id = l.product_id
INNER JOIN 'catalog_product_index_price_idx' AS 'pi' ON ce.entity_id = pi.entity_id
INNER JOIN 'core_website' AS 'cw' ON pi.website_id = cw.website_id
INNER JOIN 'core_store_group' AS 'csg' ON csg.website_id = cw.website_id AND cw.default_group_id = csg.group_id
INNER JOIN 'core_store' AS 'cs' ON csg.default_store_id = cs.store_id AND cs.store_id != 0
CROSS JOIN 'cataloginventory_stock' AS 'cis'
LEFT JOIN 'cataloginventory_stock_item' AS 'cisi' ON cisi.stock_id = cis.stock_id AND cisi.product_id = ce.entity_id
LEFT JOIN 'catalog_product_entity_int' AS 'tad_status' ON tad_status.entity_id = ce.entity_id AND tad_status.attribute_id = 96 AND tad_status.store_id = 0
LEFT JOIN 'catalog_product_entity_int' AS 'tas_status' ON tas_status.entity_id = ce.entity_id AND tas_status.attribute_id = 96 AND tas_status.store_id = cs.store_id WHERE (e.type_id='configurable') ORDER BY IF(IF(cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 1,cisi.is_in_stock, 1), 1, 0) DESC, pi.final_price ASC, pi.price ASC) AS 'inner' GROUP BY 'inner'.'entity_id',
'inner'.'customer_group_id',
'inner'.'website_id' ON DUPLICATE KEY UPDATE 'tax_class_id' = VALUES('tax_class_id'), 'orig_price' = VALUES('orig_price'), 'price' = VALUES('price'), 'min_price' = VALUES('min_price'), 'max_price' = VALUES('max_price'), 'tier_price' = VALUES('tier_price'), 'base_tier' = VALUES('base_tier'), 'group_price' = VALUES('group_price'), 'base_group_price' = VALUES('base_group_price')

 

Erst ein wenig unübersichtlich, fällt hierbei auf, dass der Versuch, die Suchergebnisse nach Preisen mit "ORDER" zu sortieren, in der Subquery statt finden soll. Was in MySQL noch gut funktioniert bzw. geduldet wird, wird hingegen in der MariaDB-Verwaltung schlichtweg ignoriert (für eine tiefergehende Begründung bzw. der korrekten Syntax, siehe unter anderem https://jira.mariadb.org/browse/MDEV-3926?focusedCommentId=28800&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-28800). Eine Lösung ist hier, in der MySQL-Query einzugreifen, die in der oben bereits erwähnten Configurable.php konstruiert wird. So können die Zeilen

 

$sortExpr = new Zend_Db_Expr("${isInStockExpr} DESC, pi.final_price ASC, pi.price ASC");
$select->order($sortExpr);

 

herausgenommen werden, da obsolet / unwirksam. Hierfür kann der "Outer Select" verändert werden, hier wird dann:

 

$outerSelect->columns(array(
'customer_group_id',
'website_id',
'tax_class_id',
'orig_price',
'price',
'min_price',
'max_price' => new Zend_Db_Expr('MAX(inner.max_price)'),
'tier_price',
'base_tier',
'group_price',
'base_group_price',
#'base_tier',
#'child_entity_id'
));

 

zu

 

$outerSelect->columns(array(
'customer_group_id',
'website_id',
'tax_class_id',
'orig_price' => new Zend_Db_Expr('MIN(inner.min_price)'),
'price' => new Zend_Db_Expr('MIN(inner.min_price)'),
'min_price' => new Zend_Db_Expr('MIN(inner.min_price)'),
'max_price' => new Zend_Db_Expr('MAX(inner.max_price)'),
'tier_price',
'base_tier',
'group_price',
'base_group_price',
#'base_tier',
#'child_entity_id'
));

 

Das Ergebnis? Jetzt wird in der Artikelliste der niedrigste Preis angezeigt und alles funktioniert wunderbar. Getestet in Magento CE 1.9.