0
可以說,這些是屬性的顏色和大小。顏色有以下選項紅色,綠色和藍色,大小有以下選項小,中,大。現在,假設產品集合中有兩種產品,一種產品是紅色的,尺寸小,另一種是綠色的,尺寸中等。所以,我要像下面如何在Magento中獲取所有屬性(在前端可見)及其相應的產品集合選項?
- 顏色輸出:紅,綠
- 尺寸:小型,中型
我不希望獲取第一屬性列表集合,然後遍歷和與它的每個產品的屬性相匹配,因爲這會非常緩慢且耗費內存。
可以說,這些是屬性的顏色和大小。顏色有以下選項紅色,綠色和藍色,大小有以下選項小,中,大。現在,假設產品集合中有兩種產品,一種產品是紅色的,尺寸小,另一種是綠色的,尺寸中等。所以,我要像下面如何在Magento中獲取所有屬性(在前端可見)及其相應的產品集合選項?
我不希望獲取第一屬性列表集合,然後遍歷和與它的每個產品的屬性相匹配,因爲這會非常緩慢且耗費內存。
我調試了分層導航在Magento中的工作原理,並基於這個思路提出了下面提到的解決方案。
try{
//Get product collection and apply filter to it if any. Here I am applying dummy color filter
$prodCollection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('color',array('in' => array(3,4))); //change this filter ad per your need
$prodCollection
->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->addUrlRewrite(Mage::getModel('catalog/layer')->getCurrentCategory()->getId());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($prodCollection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($prodCollection);
$setId = 4; //default attribute set id. change this as pre your need. You can also make this an array
//Get catalog attribute collection of some attribute sets.
$attrCollection = Mage::getResourceModel('catalog/product_attribute_collection');
$attrCollection
->setItemObjectClass('catalog/resource_eav_attribute')
->setAttributeSetFilter($setId)
->addStoreLabel(Mage::app()->getStore()->getId())
->setOrder('position', 'ASC');
$attrCollection->addIsFilterableFilter(); //Check if attributes are filterable or not
$attrCollection->load();
$connection = Mage::getSingleton('core/resource')->getConnection('core_read');
$filterResourceModel = Mage::getResourceModel('catalog/layer_filter_attribute');
//Apply filter to product collection, if any
if(1){ //Check if any filters are applied on product collection from query string (?color=4&size=8)
foreach($attrCollection as $attribute){
//For now just for testing purpose, I have hardcoded it to work only for single attribute i.e. color
if($attribute->getAttributeCode() != 'color'){
continue;
}
//I am assuming color filter is applied twice
$filterName = 'color';
$filterId = 92;
$filterVal = array(3,4);
$tableAlias = $attribute->getAttributeCode() . '_fa';
$conditions = array(
"{$tableAlias}.entity_id = e.entity_id",
$connection->quoteInto("{$tableAlias}.attribute_id = ?", $attribute->getAttributeId()),
$connection->quoteInto("{$tableAlias}.store_id = ?", $prodCollection->getStoreId()),
$connection->quoteInto("{$tableAlias}.value IN (?)", $filterVal)
);
$prodCollection->getSelect()->join(
array($tableAlias => $filterResourceModel->getMainTable()),
implode(' AND ', $conditions),
array()
);
}
}
//Iterate each attribute one by one. For now just for testing purpose, I have hardcoded it to work only for single attribute i.e. color
foreach($attrCollection as $attribute){
if($attribute->getAttributeCode() != 'color'){
continue;
}
//find attributes options
$options = $attribute->getFrontend()->getSelectOptions();
// clone select from collection with filters
$select = clone $prodCollection->getSelect();
// reset columns, order and limitation conditions
$select->reset(Zend_Db_Select::COLUMNS);
$select->reset(Zend_Db_Select::ORDER);
$select->reset(Zend_Db_Select::LIMIT_COUNT);
$select->reset(Zend_Db_Select::LIMIT_OFFSET);
$tableAlias = sprintf('%s_idx', $attribute->getAttributeCode());
$conditions = array(
"{$tableAlias}.entity_id = e.entity_id",
$connection->quoteInto("{$tableAlias}.attribute_id = ?", $attribute->getAttributeId()),
$connection->quoteInto("{$tableAlias}.store_id = ?", Mage::app()->getStore()->getId()), //$filter->getStoreId()
);
$select
->join(
array($tableAlias => $filterResourceModel->getMainTable()),
join(' AND ', $conditions),
array('value', 'count' => new Zend_Db_Expr("COUNT({$tableAlias}.entity_id)")))
->group("{$tableAlias}.value");
$optionsCount = $connection->fetchPairs($select);
$data = array();
foreach ($options as $option) {
if (is_array($option['value'])) {
continue;
}
if (Mage::helper('core/string')->strlen($option['value'])) {
$data[] = array(
'label' => $option['label'],
'value' => $option['value'],
'count' => isset($optionsCount[$option['value']]) ? $optionsCount[$option['value']] : 0,
);
}
}
echo '<pre>'; print_r($data); die('<><>');
}
}catch(Exception $e){
}
假設你已經有產品集合已經,可以遍歷每個產品的配置屬性,並將它們添加到陣列來輸出作爲例如 –
@Robbie Averill的 - 如果有什麼產品集合了數千種產品。然後它會花費很多時間。不能使用單個SQL查詢來完成。在分層導航中,只有那些屬於正在使用的產品集合的屬性和選項才能實現。 –
嗨Vineet,是的這是一個很好的問題,但你必須總是考慮加載時間處理這麼多的實體。你需要做什麼?它會多久運行一次?你可以用SQL來做到這一點,但它會涉及許多表連接 –