2012-12-01 41 views
4

我想覆盖目录/图层模型的函数prepareProductCollection($ collection)。无法使用产品集合上的type_id加载和过滤

因为,我只是想显示简单的产品,所以我想要做的:

public function prepareProductCollection($collection) 
    { 
     $collection 
      ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes()) 
      ->addMinimalPrice() 
      ->addFinalPrice() 
      ->addTaxPercents() 
      ->addUrlRewrite($this->getCurrentCategory()->getId()); 

     Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection); 
     Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection); 

     $collection 
     ->addAttributeToSelect('type_id') 
     ->addAttributeToFilter('type_id','simple'); 
     echo $collection->getSelect()->__toString(); 

    } 

但是,当我这样做,我有这样的错误:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'e.type_id' in 'where clause' 

Trace: 
#0 /Users/Ditchou/Documents/ProjetsWeb/lolote/lib/Varien/Db/Statement/Pdo/Mysql.php(110): Zend_Db_Statement_Pdo->_execute(Array) 
#1 /Users/Ditchou/Documents/ProjetsWeb/lolote/lib/Zend/Db/Statement.php(300): Varien_Db_Statement_Pdo_Mysql->_execute(Array) 
#2 /Users/Ditchou/Documents/ProjetsWeb/lolote/lib/Zend/Db/Adapter/Abstract.php(479): Zend_Db_Statement->execute(Array) 
#3 /Users/Ditchou/Documents/ProjetsWeb/lolote/lib/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract->query('SELECT FLOOR((R...', Array) 
#4 /Users/Ditchou/Documents/ProjetsWeb/lolote/lib/Varien/Db/Adapter/Pdo/Mysql.php(419): Zend_Db_Adapter_Pdo_Abstract->query('SELECT FLOOR((R...', Array) 
#5 /Users/Ditchou/Documents/ProjetsWeb/lolote/lib/Zend/Db/Adapter/Abstract.php(808): Varien_Db_Adapter_Pdo_Mysql->query(Object(Varien_Db_Select), Array) 
#6 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Model/Resource/Layer/Filter/Price.php(274): Zend_Db_Adapter_Abstract->fetchPairs(Object(Varien_Db_Select)) 
#7 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Model/Layer/Filter/Price.php(158): Mage_Catalog_Model_Resource_Layer_Filter_Price->getCount(Object(Mage_Catalog_Model_Layer_Filter_Price), 10) 
#8 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Model/Layer/Filter/Price.php(115): Mage_Catalog_Model_Layer_Filter_Price->getRangeItemCounts(10) 
#9 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Model/Layer/Filter/Price.php(314): Mage_Catalog_Model_Layer_Filter_Price->getPriceRange() 
#10 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Model/Layer/Filter/Abstract.php(151): Mage_Catalog_Model_Layer_Filter_Price->_getItemsData() 
#11 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Model/Layer/Filter/Abstract.php(120): Mage_Catalog_Model_Layer_Filter_Abstract->_initItems() 
#12 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Model/Layer/Filter/Abstract.php(109): Mage_Catalog_Model_Layer_Filter_Abstract->getItems() 
#13 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Block/Layer/Filter/Abstract.php(132): Mage_Catalog_Model_Layer_Filter_Abstract->getItemsCount() 
#14 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/design/frontend/decostore/default/template/catalog/layer/view.phtml(49): Mage_Catalog_Block_Layer_Filter_Abstract->getItemsCount() 
#15 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Template.php(241): include('/Users/Ditchou/...') 
#16 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Template.php(272): Mage_Core_Block_Template->fetchView('frontend/decost...') 
#17 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Template.php(286): Mage_Core_Block_Template->renderView() 
#18 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Core_Block_Template->_toHtml() 
#19 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Text/List.php(43): Mage_Core_Block_Abstract->toHtml() 
#20 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Core_Block_Text_List->_toHtml() 
#21 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Abstract.php(582): Mage_Core_Block_Abstract->toHtml() 
#22 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Abstract.php(526): Mage_Core_Block_Abstract->_getChildHtml('left', true) 
#23 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/design/frontend/decostore/default/template/page/2columns-left.phtml(19): Mage_Core_Block_Abstract->getChildHtml('left') 
#24 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Template.php(241): include('/Users/Ditchou/...') 
#25 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Template.php(272): Mage_Core_Block_Template->fetchView('frontend/decost...') 
#26 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Template.php(286): Mage_Core_Block_Template->renderView() 
#27 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Core_Block_Template->_toHtml() 
#28 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Model/Layout.php(555): Mage_Core_Block_Abstract->toHtml() 
#29 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Controller/Varien/Action.php(390): Mage_Core_Model_Layout->getOutput() 
#30 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/controllers/CategoryController.php(159): Mage_Core_Controller_Varien_Action->renderLayout() 
#31 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Controller/Varien/Action.php(419): Mage_Catalog_CategoryController->viewAction() 
#32 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(250): Mage_Core_Controller_Varien_Action->dispatch('view') 
#33 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Controller/Varien/Front.php(176): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http)) 
#34 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Core/Model/App.php(354): Mage_Core_Controller_Varien_Front->dispatch() 
#35 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/Mage.php(683): Mage_Core_Model_App->run(Array) 
#36 /Users/Ditchou/Documents/ProjetsWeb/lolote/index.php(87): Mage::run('', 'store') 
#37 {main} 

的错误似乎发生这里: #6 /Users/Ditchou/Documents/ProjetsWeb/lolote/app/code/core/Mage/Catalog/Model/Resource/Layer/Filter/Price.php(274):Zend_Db_Adapter_Abstract-> fetchPairs(Object(Varien_Db_Select) )

我不明白,因为我根本就

$collectionSimple = Mage::getResourceModel('catalog/product_collection') 
    ->addAttributeToFilter('type_id', array('eq' => 'simple')); 

的SQL请求的回声给我:

SELECT `e`.*, `cat_index`.`position` AS `cat_index_position`, `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`, IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price` FROM `catalog_product_entity` AS `e` INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id=1 AND cat_index.visibility IN(2, 4) AND cat_index.category_id='3' INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0 WHERE (`e`.`type_id` = 'simple') 

它的工作原理。

为什么图层模型的集合是不同的?

回答

8

你确定这是你得到的错误吗?在Magento的1.7.x,当我上面提供的一个替代方法prepareProductCollection身体,我得到这个错误

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'e.min_price' in 'where clause' 

那是因为我的prepareProductCollection没有设置相同的属性原件。对于初学者,请确保你的。如果您正在使用基于配置的重写进行此操作,请在您的方法开始时致电

parent::prepareProductCollection($collection); 

。如果您使用localcommunity代码池覆盖,则需要复制/粘贴core文件中的代码。在1.7.1,将这个样子

$collection 
     ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes()) 
     ->addMinimalPrice() 
     ->addFinalPrice() 
     ->addTaxPercents() 
     ->addUrlRewrite($this->getCurrentCategory()->getId()); 

    Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection); 
    Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection); 

    $collection 
     ->addAttributeToSelect('type_id') 
     ->addAttributeToFilter('type_id','simple'); 

如果不帮助你,跟踪你的调用堆栈 - 如果你的错误真的是1054 Unknown column 'e.type_id' in 'where clause'然后我的猜测是,你有什么地方运行一些自定义代码,将集合的过滤器复制到不同的集合中。

另外,还可以通过使用

echo $collection->getSelect()->__toString(); 

得到一个集合的主要SQL查询应该给你足够的调试信息走了。

更新:好的,基于上面的新信息,这似乎只在有价格过滤器和/或索引处于特定状态的情况下才会启动。

这是你的问题。看看这个调用堆栈线

#7 app/code/core/Mage/Catalog/Model/Layer/Filter/Price.php(158): Mage_Catalog_Model_Resource_Layer_Filter_Price->getCount(Object(Mage_Catalog_Model_Layer_Filter_Price), 10) 

如果你跳到getCount方法,你会看到_getSelect

#File: app/code/core/Mage/Catalog/Model/Resource/Layer/Filter/Price.php 
public function getCount($filter, $range) 
{ 
    $select = $this->_getSelect($filter); 

通话如果你看看_getSelect定义,

#partial method reproduction 
#File: app/code/core/Mage/Catalog/Model/Resource/Layer/Filter/Price.php 
protected function _getSelect($filter) 
{  
    $collection = $filter->getLayer()->getProductCollection(); 
    $collection->addPriceData($filter->getCustomerGroupId(), $filter->getWebsiteId()); 
    if (!is_null($collection->getCatalogPreparedSelect())) { 
     $select = clone $collection->getCatalogPreparedSelect(); 
    } else { 
     $select = clone $collection->getSelect(); 
    } 

你会看到Magento是克隆从集合中选择,然后修改它以选择从索引表

// processing FROM part 
    $priceIndexJoinPart = $fromPart[Mage_Catalog_Model_Resource_Product_Collection::INDEX_TABLE_ALIAS]; 
    $priceIndexJoinConditions = explode('AND', $priceIndexJoinPart['joinCondition']); 
    $priceIndexJoinPart['joinType'] = Zend_Db_Select::FROM; 
    $priceIndexJoinPart['joinCondition'] = null; 
    $fromPart[Mage_Catalog_Model_Resource_Product_Collection::MAIN_TABLE_ALIAS] = $priceIndexJoinPart; 
    unset($fromPart[Mage_Catalog_Model_Resource_Product_Collection::INDEX_TABLE_ALIAS]); 
    $select->setPart(Zend_Db_Select::FROM, $fromPart); 
    foreach ($fromPart as $key => $fromJoinItem) { 
     $fromPart[$key]['joinCondition'] = $this->_replaceTableAlias($fromJoinItem['joinCondition']); 
    } 
    $select->setPart(Zend_Db_Select::FROM, $fromPart); 

由于索引表没有一个type_id列,上述股票的Magento代码是与你的变化不兼容。如果我要继续在此,我想

  1. 移动到改写为基础的方法

  2. 创建一个重写,增加了你的type_id过滤器后您的倍率

  3. 创建在_getSelect方法高于第二重写检查选择用于type_id滤波器,并且如果它发现它,删除它

或者,您可以尝试找到一种不同的方法来重写您的收集对象,使其更接近它的使用位置。

祝你好运!

+0

我仍然有错误,我试过你的解决方案。我使用trace和sql输出更新了我的问题 – Sebastien

+0

@Sebastien更新了有关更多信息的问题。 Magento克隆你的集合,并在有价格过滤器时使用它来查询索引表。索引表没有type_id列,所以这是事情的落脚点。 –

+0

感谢艾伦详细回答了这个问题,并感谢Sebastien发布这个问题在stackoverflow。 :)。 –

1

我在2-3周前尝试将图层导航添加到自定义集合(而不是依赖类别集合和搜索集合的集合)时,只是遇到了同样的问题。我遇到了与分层导航中使用的价格过滤器处理相同的问题。 像Alan建议的那样,在Magento 1.7中,他们对用于价格过滤选项的select sql进行了优化。他们删除FROM sql部分(它是包含type_id属性的产品实体),并将price_index相关表作为主要部分 - 在查询的FROM部分中使用该表。因此,基本上从中选择数据的表格不再是产品实体表格(您将失去所有产品基本属性),主表格将成为产品索引。这是Magento团队添加的1.7版本的核心更新。

我也有一个工作解决方案,我明天将与您分享,我现在无法访问代码。

0

当我从select语句中删除导致错误的字段时,我在扩展_getSelect函数时没有为侧边栏中的价格筛选器返回正确的设置问题。

所以相反,为了解决不存在的字段问题,我使用了一个存在的字段entity_id。我扩展了Mage_Catalog_Model_Category,更改函数getProductCollection:

$collection = Mage::getResourceModel('catalog/product_collection') 
    ->setStoreId($this->getStoreId()) 
    ->addAttributeToFilter('type_id', array('eq' => 'simple')); 
// Get the product ids of the filtered collection 
$entityIds = $collection->getAllIds(); 

$collection = Mage::getResourceModel('catalog/product_collection') 
    ->setStoreId($this->getStoreId()) 
    ->addCategoryFilter($this) 
    // Apply the product ids as a filter 
    ->addIdFilter($entityIds,false); 

return $collection; 
+2

注意,这种方法可能会导致很大的性能缺陷 –