bestsellers

Liste des bestsellers VS flat catalog dans Magento

Magento utilise par défaut le modèle EAV dans sa base de données mais il est également possible d'utiliser le flat catalog dans votre magasin. L'activation de cette option améliorera vos performances, mais peut aussi s'accompagner de problèmes lors de l'affichage de produits. L'affichage d'une liste de produits bestsellers est un bon exemple de problème que peut engendrer l'activation du flat catalog.

Une liste de bestsellers peut être construite en utilisant une collection :

$collection = Mage::getResourceModel('reports/product_collection');

$collection->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());

$collection = $this->_addProductAttributesAndPrices($collection)
    ->addOrderedQty()
    ->addStoreFilter()
    ->setOrder('ordered_qty', 'desc')
    ->setPageSize(5)
    ->setCurPage(1);

$this->setProductCollection($collection);

De cette façon, nous créons une collection de produits ordonnés selon le nombre de fois qu'un produit a été commandé. Cependant, lors de l'affichage des produits de cette collection dans une template vous verrez que certaines données (telles que le nom ou l'image) ne s'afficheront pas si le flat catalog est activé. Cela provient de la méthode addOrderedQty qui effectue une mauvaise requête. Voici la solution :

La méthode addOrderedQty appartient au module Mage/Reports. Vous trouverez son code dans le fichier Magento app/code/core/Mage/Reports/Model/Mysql4/Product/Collection.php. La partie nous intéressant se trouve à la fin de cette méthode :

$this->getSelect()
    ->joinInner(
        array('e' => $this->getProductEntityTableName()),
        "e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}"
    )
    ->group('e.entity_id')
    ->having('ordered_qty > 0');

Pour résoudre le problème de l'utilisation du flat catalog vous devez simplement réécrire la méthode en utilisant un rewrite et remplacer le code défaillant par le code suivant:

if ($this->isEnabledFlat()) {
    $this->getSelect()->joinInner(
        array('e' => $this->getResource()->getFlatTableName()),
        "e.entity_id = order_items.{$productIdFieldName}{$productTypes}"
    );
}
else {
    $this->getSelect()
        ->joinInner(
            array('e' => $this->getProductEntityTableName()),
            "e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}"
        );
}

$this->getSelect()
    ->group('e.entity_id')
    ->having('ordered_qty > 0');

De cette manière, la requête interroge la bonne table en fonction de l'activation ou non du flat catalog. Le problème est alors résolu.

Traduction par Laurent Clouet