Magento BestSeller 模块 - 汇总可配置产品并将其添加回
这已经困扰我很长一段时间了。基本上,我们想要实现的目标是在首页的畅销书上列出产品的销量。对于简单产品,这工作正常,但是对于可配置产品,它们将显示为订购数量为 0。
我以某种方式需要找到一种方法来获取可配置产品,找到附加到它们的简单产品,将这些简单产品的销售量相加产品,将其添加回可配置产品 ID 并将此信息反馈回来,以便它将列出已售出的正确数量的可配置产品。
我认为,我已经放置了需要更改的代码区域。如果有人可以提供帮助,将不胜感激!
集合.php
class Luxe_Bestsellers_Model_Mysql4_Product_Collection extends Mage_Reports_Model_Mysql4_Product_Collection
{
public function addOrderedQty($from = '', $to = '', $getComplexProducts=false)
{
$qtyOrderedTableName = $this->getTable('sales/order_item');
$qtyOrderedFieldName = 'qty_ordered';
$productIdFieldName = 'product_id';
if (!$getComplexProducts) {
$compositeTypeIds = Mage::getSingleton('catalog/product_type')->getCompositeTypes();
$productTypes = $this->getConnection()->quoteInto(' AND (e.type_id NOT IN (?))', $compositeTypeIds);
} else {
$productTypes = '';
}
if ($from != '' && $to != '') {
$dateFilter = " AND `order`.created_at BETWEEN '{$from}' AND '{$to}'";
} else {
$dateFilter = "";
}
$this->getSelect()->reset()->from(
array('order_items' => $qtyOrderedTableName),
array('ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})")
);
$_joinCondition = $this->getConnection()->quoteInto(
'order.entity_id = order_items.order_id AND order.state<>?', Mage_Sales_Model_Order::STATE_CANCELED
);
$_joinCondition .= $dateFilter;
$this->getSelect()->joinInner(
array('order' => $this->getTable('sales/order')),
$_joinCondition,
array()
);
$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');
return $this;
}
}
列表.php
class Luxe_Bestsellers_Block_List extends Mage_Catalog_Block_Product_List
{
protected $_defaultToolbarBlock = 'bestsellers/list_toolbar';
protected function _beforeToHtml() {
$this->addPriceBlockType('bundle', 'bundle/catalog_product_price', 'bundle/catalog/product/price.phtml');
return parent::_beforeToHtml();
}
public function _toHtml()
{
if ($this->_productCollection->count()) {
return parent::_toHtml();
} else {
return '';
}
}
public function getTimeLimit()
{
if ($this->getData('time_limit_in_days')) {
return intval($this->getData('time_limit_in_days'));
} else {
return intval(Mage::getStoreConfig('bestsellers/bestsellers/time_limit_in_days'));
}
}
public function getBlockTitle()
{
if ($this->getData('title')) {
return $this->getData('title');
} else {
return Mage::getStoreConfig('bestsellers/bestsellers/title');
}
}
public function isShowOutOfStock() {
return (bool)Mage::getStoreConfig('bestsellers/bestsellers/show_out_of_stock');
}
public function getProductsLimit()
{
if ($this->getData('limit')) {
return intval($this->getData('limit'));
} else {
return $this->getToolbarBlock()->getLimit();
}
}
public function getDisplayMode()
{
return $this->getData('display_mode');
}
/**
* Retrieve loaded category collection
*
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
protected function _getProductCollection()
{
if (is_null($this->_productCollection)) {
$layer = Mage::getModel('catalog/layer');
$bestsellers = Mage::getResourceModel('reports/product_collection');
if ($this->getTimeLimit()) {
$product = Mage::getModel('catalog/product');
$todayDate = $product->getResource()->formatDate(time());
$startDate = $product->getResource()->formatDate(time() - 60 * 60 * 24 * $this->getTimeLimit());
$bestsellers->addOrderedQty($startDate, $todayDate, true);
} else {
$bestsellers->addOrderedQty('', '', true);
}
$bestsellers->addStoreFilter()
->setOrder('ordered_qty', 'desc')
->setPageSize($this->getProductsLimit());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($bestsellers);
if ($layer->getCurrentCategory()->getId() != Mage::app()->getStore()->getRootCategoryId()) {
$bestsellers->addCategoryFilter($layer->getCurrentCategory());
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($bestsellers);
}
if (!$this->isShowOutOfStock()) {
Mage::getModel('cataloginventory/stock')->addInStockFilterToCollection($bestsellers);
}
$bestsellers->getSelect()->where('order.store_id = ?', Mage::app()->getStore()->getId());
$productIds = array();
foreach ($bestsellers as $p) {
$productIds[] = $p->getId();
}
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
$collection->addIdFilter($productIds)
->addAttributeToSelect($attributes)
->addMinimalPrice()
->addFinalPrice();
$this->_productCollection = $collection;
}
return $this->_productCollection;
}
/**
* Translate block sentence
*
* @return string
*/
public function __()
{
$args = func_get_args();
$expr = new Mage_Core_Model_Translate_Expr(array_shift($args), 'Mage_Catalog');
array_unshift($args, $expr);
return Mage::app()->getTranslator()->translate($args);
}
}
This has been bugging me for quite a while. Basically, what we are trying to achieve is in the bestsellers on our front page, to have the products listed in the amount sold. For simple products this works fine, however for configurable products they will be displayed as a quantity ordered of 0.
I somehow need to find a way to get the configurable products, find the simple products attached to them, sum the amount sold of these simple products, add this back to the configurable products ID and feed this information back in so it will list the configurable product with the right amount that has been sold.
I have placed, what I believe, the areas of code that require changing. If anyone could help it would be very much appreciated!
Collection.php
class Luxe_Bestsellers_Model_Mysql4_Product_Collection extends Mage_Reports_Model_Mysql4_Product_Collection
{
public function addOrderedQty($from = '', $to = '', $getComplexProducts=false)
{
$qtyOrderedTableName = $this->getTable('sales/order_item');
$qtyOrderedFieldName = 'qty_ordered';
$productIdFieldName = 'product_id';
if (!$getComplexProducts) {
$compositeTypeIds = Mage::getSingleton('catalog/product_type')->getCompositeTypes();
$productTypes = $this->getConnection()->quoteInto(' AND (e.type_id NOT IN (?))', $compositeTypeIds);
} else {
$productTypes = '';
}
if ($from != '' && $to != '') {
$dateFilter = " AND `order`.created_at BETWEEN '{$from}' AND '{$to}'";
} else {
$dateFilter = "";
}
$this->getSelect()->reset()->from(
array('order_items' => $qtyOrderedTableName),
array('ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})")
);
$_joinCondition = $this->getConnection()->quoteInto(
'order.entity_id = order_items.order_id AND order.state<>?', Mage_Sales_Model_Order::STATE_CANCELED
);
$_joinCondition .= $dateFilter;
$this->getSelect()->joinInner(
array('order' => $this->getTable('sales/order')),
$_joinCondition,
array()
);
$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');
return $this;
}
}
List.php
class Luxe_Bestsellers_Block_List extends Mage_Catalog_Block_Product_List
{
protected $_defaultToolbarBlock = 'bestsellers/list_toolbar';
protected function _beforeToHtml() {
$this->addPriceBlockType('bundle', 'bundle/catalog_product_price', 'bundle/catalog/product/price.phtml');
return parent::_beforeToHtml();
}
public function _toHtml()
{
if ($this->_productCollection->count()) {
return parent::_toHtml();
} else {
return '';
}
}
public function getTimeLimit()
{
if ($this->getData('time_limit_in_days')) {
return intval($this->getData('time_limit_in_days'));
} else {
return intval(Mage::getStoreConfig('bestsellers/bestsellers/time_limit_in_days'));
}
}
public function getBlockTitle()
{
if ($this->getData('title')) {
return $this->getData('title');
} else {
return Mage::getStoreConfig('bestsellers/bestsellers/title');
}
}
public function isShowOutOfStock() {
return (bool)Mage::getStoreConfig('bestsellers/bestsellers/show_out_of_stock');
}
public function getProductsLimit()
{
if ($this->getData('limit')) {
return intval($this->getData('limit'));
} else {
return $this->getToolbarBlock()->getLimit();
}
}
public function getDisplayMode()
{
return $this->getData('display_mode');
}
/**
* Retrieve loaded category collection
*
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
protected function _getProductCollection()
{
if (is_null($this->_productCollection)) {
$layer = Mage::getModel('catalog/layer');
$bestsellers = Mage::getResourceModel('reports/product_collection');
if ($this->getTimeLimit()) {
$product = Mage::getModel('catalog/product');
$todayDate = $product->getResource()->formatDate(time());
$startDate = $product->getResource()->formatDate(time() - 60 * 60 * 24 * $this->getTimeLimit());
$bestsellers->addOrderedQty($startDate, $todayDate, true);
} else {
$bestsellers->addOrderedQty('', '', true);
}
$bestsellers->addStoreFilter()
->setOrder('ordered_qty', 'desc')
->setPageSize($this->getProductsLimit());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($bestsellers);
if ($layer->getCurrentCategory()->getId() != Mage::app()->getStore()->getRootCategoryId()) {
$bestsellers->addCategoryFilter($layer->getCurrentCategory());
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($bestsellers);
}
if (!$this->isShowOutOfStock()) {
Mage::getModel('cataloginventory/stock')->addInStockFilterToCollection($bestsellers);
}
$bestsellers->getSelect()->where('order.store_id = ?', Mage::app()->getStore()->getId());
$productIds = array();
foreach ($bestsellers as $p) {
$productIds[] = $p->getId();
}
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
$collection->addIdFilter($productIds)
->addAttributeToSelect($attributes)
->addMinimalPrice()
->addFinalPrice();
$this->_productCollection = $collection;
}
return $this->_productCollection;
}
/**
* Translate block sentence
*
* @return string
*/
public function __()
{
$args = func_get_args();
$expr = new Mage_Core_Model_Translate_Expr(array_shift($args), 'Mage_Catalog');
array_unshift($args, $expr);
return Mage::app()->getTranslator()->translate($args);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
感谢您发布示例代码!我能够使用它来创建一个对我们双方都适用的解决方案。
我发现可配置产品销售额已正确汇总,但未包含在结果中;相反,他们的子产品出现了。我的解决方案是包含可配置产品,在
catalog_product_super_link
表上执行左连接,并过滤掉任何具有parent_id
的内容。以下是您需要进行的更改:Collection.php:
List.php - 找到以下两行...
...并将其更改为:
我的更改添加了两个新的可选参数,它们都默认为
true
,以免破坏现有功能。$getComplexChildProducts
设置为false
时,可配置产品的所有子项将从结果中删除。$getRemovedProducts
确定以前订购的产品(已从 Magento 中删除)是否也应显示。请注意,您的报告统计数据需要是最新的才能获得准确的结果。
希望这有帮助!如果您有任何疑问,请告诉我。
Thanks for posting that sample code! I was able to use it to create a solution which should work well for both of us.
I found that configurable product sales are being summed correctly but aren't being included in the results; their child products appear instead. My solution was to include configurable products, do a left join on the
catalog_product_super_link
table, and filter out anything that has aparent_id
. Here are the changes you'll need to make:Collection.php:
List.php - Find the following two lines...
... and change them to:
My changes added two new optional parameters, which both default to
true
, as to not break existing functionality.$getComplexChildProducts
is set tofalse
, all child items of the configurable product will be removed from the results.$getRemovedProducts
determines whether or not previously ordered products (which have since been deleted from Magento) should also appear.Please note that your report statistics will need to be up-to-date in order to get accurate results.
Hope this helps! Let me know if you have any questions.
您可以使用以下代码片段将简单产品附加到可配置产品。我不确定这是否100%正确,我自己没有尝试过。
You can use the following piece of code to get the simple products attached to the configurable product. I'm not sure if this is 100% correct, I haven't tried it myself.