0

カテゴリ別に最も売れた製品を取得して、ナビゲーションの特定の部分に表示する可能性を探しています。製品を表示することは問題ではなく、それらを取得することです。

私はすでにさまざまなキーワードで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() . '_';
        }
    }

これには 2 つの問題があります。まず、Magento がさらに遅くなります。第二$product->getOrderedQty()に、検索のさまざまな結果で見つけた方法が機能しません。今、他に何を試すことができるのか本当にわかりません。非常に感謝している助けを探しています。ありがとう!

4

2 に答える 2

0

サンプル スクリプトで多くのオブジェクト ラッパーを使用しています。load複数のループにカプセル化されたようなメソッドは、大きな遅延を引き起こし、大量のメモリを使用する可能性があります (製品コレクションのサイズに基づきます)。

先日この問題に対処したとき、パフォーマンスを向上させるために、オブジェクトの代わりに直接の ORM メソッドを使用することにしました。

ベストセラーを表示するには、2 つの方法があります。集計されたベストセラー テーブル ( など) を使用すると、リソースの消費が少なくなりますがsales_bestsellers_aggregated_daily、大きな欠点があります。これらのテーブル内のデータは自動的に更新されません。これは管理レポート セクションで使用され、統計の更新を選択した場合にのみ更新されます。

もう 1 つのより信頼性の高い方法は、sales_flat_order_itemテーブルを結合して各製品の sales_qty を取得することです。自分で数えなければならないので、明らかにリソースを消費します。

私のスクリプトでは、後者のパスを選択しました。ロジック要件を満たすように変更しました。またjoins、カテゴリ名を取得するためにいくつか追加しましたが、必要ないかもしれません。しかし、十分な話です:)これが私のtest.phpシェルスクリプトのコードです:

<?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は、シェルフォルダーにファイルを作成し、提供したコードをファイルに挿入します。usageHelpコマンド ラインの php 呼び出しに慣れていないかどうかを確認してください。

PS mem_usage と時間を追跡するためにいくつかのベンチマークを追加しました。

更新問題をさらに検討すると、Zend_Dbアダプターのみを使用して各カテゴリのベストセラーを取得するよりエレガントな方法を見つけました. category_id結果には (Magento オブジェクトではなく) =>接続のみが含まれますproduct_idが、はるかに簡単で全体的に優れています。このコードは、ベンチマークブロックの間を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";
    });
于 2012-10-11T11:30:02.303 に答える
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; ?>

お役に立てれば

于 2012-10-11T11:36:03.530 に答える