2012-10-11 15 views
0

我在尋找一種可能性,以按類別獲得最暢銷的產品,以在導航的特定部分顯示它。顯示產品不是問題,而是獲得它們。顯示Magento中導航中的每個類別的暢銷書1.7

我已經使用不同的關鍵字通過Google進行了深入的搜索,但我得到的都是過時的插件,對bestseller.phtml(它不會在Magento 1.7中退出)的修改以及在資源模型上設置過濾器,我再也找不到任何結果了。

所以我嘗試自己拿到產品(到目前爲止,它只是應該得到的任何產品,沒有最好的一個銷售):

$category->getId(); 
    $children = $category->getChildren(); 

    foreach($children as $child) 
    { 
     $childCategoryIdString = $child->getId(); 
     $childCategoryId = substr($childCategoryIdString, 14); 

     $childCategory = Mage::getModel('catalog/category') 
      ->load($childCategoryId); 

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

     $allIds = $productCollection->getAllIds(); 

     for($i = 0; $i < count($allIds); $i++) 
     { 
      $product = Mage::getModel('catalog/product')->load($allIds[$i]); 
      echo $product->getOrderedQty() . '_'; 
     } 
    } 

這有兩個問題:一是它使Magento的還比較慢。第二個$product->getOrderedQty(),我在我的搜索的各種結果中找到的方法不起作用。現在我不知道還有什麼可以嘗試尋找一些高度讚賞的幫助。謝謝!

回答

0

您在示例腳本中使用了很多對象包裝器。像load這樣的方法封裝成多個循環會產生巨大的延遲,並可能會導致巨大的內存使用量(基於您的產品集合大小)。

當我在前幾天提到這個問題時,我決定使用直接的ORM方法而不是對象來獲得更好的性能。

有兩種可能的方式來顯示暢銷書。使用匯總的暢銷書表(如sales_bestsellers_aggregated_daily)的資源消耗較少,但它有巨大的缺點 - 這些表中的數據不會自動更新。它用於管理報告部分,只有在您選擇刷新統計信息時纔會更新。

另一個更可靠的方法是加入sales_flat_order_item表來檢索每個產品的sales_qty。顯然它更耗費資源,因爲你必須自己計算。

在我的腳本中,我選擇了後一種路徑。我已經修改它以符合您的邏輯要求。此外,我添加了幾個joins以獲得類別名稱,您可能不需要。但足夠的說話:)這裏是我的test.php shell腳本的代碼:

<?php 
require_once 'abstract.php'; 

/** 
* Magento Test Bestsellers script 
* 
* @category Mage 
* @package  Mage_Shell 
*/ 
class Mage_Shell_Test extends Mage_Shell_Abstract 
{ 
    /** 
    * Run script 
    * 
    */ 
    public function run() 
    { 
     // benchmarking 
     $memory = memory_get_usage(); 
     $time = microtime(); 
     echo "Starting mem usage: $memory\n"; 

     $catId = $this->getArg('category'); 
     /** @var $collection Mage_Catalog_Model_Resource_Product_Collection */ 
     $collection = Mage::getResourceModel('catalog/product_collection'); 
     // join sales order items column and count sold products 
     $expression = new Zend_Db_Expr("SUM(oi.qty_ordered)"); 
     $condition = new Zend_Db_Expr("e.entity_id = oi.product_id AND oi.parent_item_id IS NULL"); 
     $collection->addAttributeToSelect('name')->getSelect() 
      ->join(array('oi' => $collection->getTable('sales/order_item')), 
      $condition, 
      array('sales_count' => $expression)) 
      ->group('e.entity_id') 
      ->order('sales_count' . ' ' . 'desc'); 
     // join category 
     $condition = new Zend_Db_Expr("e.entity_id = ccp.product_id"); 
     $condition2 = new Zend_Db_Expr("c.entity_id = ccp.category_id"); 
     $collection->getSelect()->join(array('ccp' => $collection->getTable('catalog/category_product')), 
      $condition, 
      array())->join(array('c' => $collection->getTable('catalog/category')), 
      $condition2, 
      array('cat_id' => 'c.entity_id')); 
     $condition = new Zend_Db_Expr("c.entity_id = cv.entity_id AND ea.attribute_id = cv.attribute_id"); 
     // cutting corners here by hardcoding 3 as Category Entiry_type_id 
     $condition2 = new Zend_Db_Expr("ea.entity_type_id = 3 AND ea.attribute_code = 'name'"); 
     $collection->getSelect()->join(array('ea' => $collection->getTable('eav/attribute')), 
      $condition2, 
      array())->join(array('cv' => $collection->getTable('catalog/category') . '_varchar'), 
      $condition, 
      array('cat_name' => 'cv.value')); 
     // if Category filter is on 
     if ($catId) { 
      $collection->getSelect()->where('c.entity_id = ?', $catId)->limit(1); 
     } 

     // unfortunately I cound not come up with the sql query that could grab only 1 bestseller for each category 
     // so all sorting work lays on php 
     $result = array(); 
     foreach ($collection as $product) { 
      /** @var $product Mage_Catalog_Model_Product */ 
      if (isset($result[$product->getCatId()])) { 
       continue; 
      } 
      $result[$product->getCatId()] = 'Category:' . $product->getCatName() . '; Product:' . $product->getName() . '; Sold Times:'. $product->getSalesCount(); 
     } 

     print_r($result); 

     // benchmarking 
     $memory2 = memory_get_usage(); 
     $time2 = microtime(); 
     $memDiff = ($memory2 - $memory)/1000000; 
     $timeDiff = $time2 - $time; 
     echo 'Time spent:' . $timeDiff . "s\n"; 
     echo "Ending mem usage: $memory2\n"; 
     echo "Mem used : {$memDiff}M\n"; 
    } 

    /** 
    * Retrieve Usage Help Message 
    * 
    */ 
    public function usageHelp() 
    { 
     return <<<USAGE 
Usage: php -f test.php -- [options] 
     php -f test.php -- --category 1 

    --categories <category> Filter by Category, if not specified, all categories are outputted 
    help      This help 

USAGE; 
    } 
} 

$shell = new Mage_Shell_Test(); 
$shell->run(); 

要使用它只是在你的外殼文件夾中創建一個文件test.php並插入我提供到文件的代碼。如果您不熟悉命令行php調用,請參閱usageHelp

P.S.在那裏添加了一些基準來跟蹤你的mem_usage和時間。

UPDATE進一步審查問題後,我發現更優雅的方式來獲得每個類別的暢銷品只使用Zend_Db適配器。結果將只包含category_id =>product_id連接(不是Magento對象),但它更容易和整體更好。此代碼應標杆塊之間進入run功能:

$catId = $this->getArg('category'); 

    /** @var $resource Mage_Core_Model_Resource */ 
    $resource = Mage::getModel('core/resource'); 
    /** @var $adapter Zend_Db_Adapter_Abstract */ 
    $adapter = $resource->getConnection('core_read'); 

    $select = $adapter->select() 
     ->from(array('c' => $resource->getTableName('catalog/category')), array('cat_id'=>'entity_id')) 
     ->join(array('ccp' => $resource->getTableName('catalog/category_product')), 'c.entity_id = ccp.category_id', array()) 
     ->join(array('oi' => $resource->getTableName('sales/order_item')), 'ccp.product_id = oi.product_id', array('max_qty' => new Zend_Db_Expr('SUM(oi.qty_ordered - oi.qty_canceled)'), 'product_id' => 'product_id')) 
     ->where('oi.parent_item_id is null') 
     ->group('c.entity_id') 
     ->group('oi.product_id') 
     ->order('entity_id ASC') 
     ->order('max_qty DESC'); 
    if ($catId) { 
     $select->where('c.entity_id = ?', $catId); 
    } 
    $res = $adapter->fetchAll($select); 

    $result = array(); 
    foreach ($res as $oneRes) { 
     if (isset($result[$oneRes['cat_id']])) { 
      continue; 
     } 
     $result[$oneRes['cat_id']] = $oneRes; 
    } 

    array_walk($result, function($var, $key) { 
     echo 'Category Id:' . $key . ' | Product Id:' . $var['product_id'] . ' | Sales Count:' . $var['max_qty'] . "\n"; 
    }); 
+0

對不起,我遲到的答覆,但感謝你的信息的答案!運行腳本會返回四個空數組。由於到目前爲止還沒有銷售產品,我不驚訝他們完全是空的(呃,至少不應該是內部的文本字符串?),但我得到了四個。我有四個父類別,但將$ catId定義爲「17」(我的一個子類別ID)用於測試目的。我有什麼監督嗎? – HamuSumo

+0

@HamuSumo如果您願意,請查看我的更新 –

+0

請注意,這些sales_bestsellers_aggregated會被magneto的cron調度程序系統中的cron作業填充 –

0
$visibility = array(
         Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH, 
         Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG 
       ); 
$category = new Mage_Catalog_Model_Category(); 
$category->load(2); //My cat id is 10 
$prodCollection = $category->getProductCollection()->addAttributeToFilter('visibility', $visibility)->setOrder('ordered_qty', 'desc'); 
<?php foreach($_productCollection as $_product): ?> 
//whatever you want 
<?php endforeach; ?> 

希望這有助於

+0

謝謝您的回覆!不幸的是,這段代碼做了一些奇怪的事情,因爲它輸出四次相同的兩個產品(至少回聲$ _product-> getId()) - 而我加載的類別有六個項目。所以我期望他們或沒有人(因爲目前還沒有產品銷售)。 – HamuSumo