-
16-10-2019 - |
题
TL; DR:如何过滤多个选择/下拉属性(多选择会很麻烦)?还是使用其他方法?
考虑一个产品选择/下拉属性属性,其值对应于字母的每个字母(在这种情况下为英语)。第一个选项的标签是“ A”,其值为1。“ B” IS 2,“ C”为3,依此类推:
我将此属性分配给控制层次导航过滤器。因此,用户可以单击特定值的链接,它将添加 ?my_attribute=2
进入请求参数,产品列表仅显示其属性值为“ B”的产品。
相反,我想显示任何属性值的产品大于或等于所选选项。因此,如果用户单击分层导航中的“ B”链接,结果将是“ BZ”(2-26)的每个产品。
URL结构: ?my_attribute=2&my_attribute_3&my_attribute=4...
将是丑陋的,而且它不起作用,但是这个想法就在那里。 ?my_attribute=2-26
显然是理想的,但是这不是Magento所做的。
奇怪的是,使用高级搜索提供了此URL结构(通过高级搜索控制器而不是分层导航):
?my_attribute%5B%5D=7&my_attribute%5B%5D=8&my_attribute%5B%5D=9&my_attribute%5B%5D=10
这确实提供了预期的结果;但是,这种结构不适用于类别/分层页面,而仅适用于高级搜索。
我正在尝试确定这一点是更好的道路。我是否应该放弃所有内置导航的内置有用性,而是重写 product_list
基于我的属性值的Block加载产品集合?还是我应该从高级搜索结果中调整一些功能以满足我的需求?
似乎最好仅保留分层的导航功能,以便其他产品过滤器继续按预期工作。但是,似乎并不能同时选择来自单个属性的多个值。另外,解决方法是使用多选属性,如果将产品分配为“ B”,则必须从“ BZ”中分配所有选项。尽管这将提供最大的即时结果(一切都将在没有更多修改的情况下起作用),但它肯定是一个草率的解决方案,将来会容易出错且笨拙。
解决方案
在这种情况下,我所做的是重写模型和相应的资源,因此首先重写类 Mage_Catalog_Model_Layer_Filter_Attribute
能够接受多个值。就我而言,我将逗号用作分离器,因此我可以过滤 ?my_attribute=1,2,3
在方法中 apply()
我解析将不同值放在数组中的属性:
public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
{
$filter = $request->getParam($this->_requestVar);
if (is_array($filter)) {
return $this;
}
// MP customized
$filter = explode(',', $filter);
if (count($filter) < 1) {
return $this;
} else if ($filter == '') {
return $this;
}
if (count($filter) == 1) {
$filter = $filter[0];
}
if ($filter == '') {
return $this;
}
if ($filter) {
$this->_initItems();
$this->_getResource()->applyFilterToCollection($this, $filter);
$text = '';
foreach ($filter as $att) {
($text == '') ? $text = $this->_getOptionText($att) : $text .= ', '.$this->_getOptionText($att);
}
if (count($filter) == 1) {
$text = $this->_getOptionText($filter);
}
$this->getLayer()->getState()->addFilter($this->_createItem($text, $filter));
}
// End MP customized
return $this;
}
然后在文件中 Mage_Catalog_Model_Resource_Eav_Mysql4_Layer_Filter_Attribute
您必须确保您能够在查询中过滤多个值,因此我重写了以下方法:
public function applyFilterToCollection($filter, $value)
{
$collection = $filter->getLayer()->getProductCollection();
$attribute = $filter->getAttributeModel();
$connection = $this->_getReadAdapter();
$tableAlias = $attribute->getAttributeCode() . '_idx';
$conditions = array(
"{$tableAlias}.entity_id = e.entity_id",
$connection->quoteInto("{$tableAlias}.attribute_id = ?", $attribute->getAttributeId()),
$connection->quoteInto("{$tableAlias}.store_id = ?", $collection->getStoreId()),
$connection->quoteInto("{$tableAlias}.value IN (?)", $value)
); // Added IN (?) notation for arrays
$collection->getSelect()->join(
array($tableAlias => $this->getMainTable()),
join(' AND ', $conditions),
array()
// MP Need distinct here to avoid getting the same config product from
// different basic products when filtering for different values
// in the same attribute
)->distinct(true);
return $this;
}
其他提示
这是带有自定义产品集合的分层导航
<?php
require_once('app/Mage.php'); //Must have file to begin
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); //Initialize store
$catId = Mage::app()->getRequest()->getParam('categoryId'); //Pass categoryId in get variable
$storeId = Mage::app()->getWebsite(true)->getDefaultGroup()->getDefaultStoreId();
$page_no = Mage::app()->getRequest()->getParam('page_no');
$params = Mage::app()->getRequest()->getParams(); //Pass attributes in key=>value form to filter results.
$category = Mage::getModel('catalog/category')->load($catId);
$layer = Mage::getModel("catalog/layer");
$layer->setCurrentCategory($category);
$attributes = $layer->getFilterableAttributes(); //get all filterable attributes available in selected category layered navigation
$attr = array();
foreach ($attributes as $attribute) {
if ($attribute->getAttributeCode() == 'price') {
$filterBlockName = 'catalog/layer_filter_price';
} elseif ($attribute->getBackendType() == 'decimal') {
$filterBlockName = 'catalog/layer_filter_decimal';
} else {
$filterBlockName = 'catalog/layer_filter_attribute';
}
$attr[$attribute->getAttributeCode()] = $attribute->getFrontendLabel();
}
$filters = array_intersect_key($params, $attr);
$collection = $category->getProductCollection()
->addAttributeToFilter(
'status', array('eq' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED))
->addAttributeToSelect('*');
foreach ($filters as $key => $value) {
if($key == 'price'){
$priceFilter = explode('-', $value);
$collection->addAttributeToFilter('price', array('gteq' => $priceFilter[0]));
$collection->addAttributeToFilter('price', array('lteq' => $priceFilter[1]));
}
else{
$codeId = Mage::getResourceModel('eav/entity_attribute')
->getIdByCode('catalog_product', $key)
$collection->getSelect()->join(array('at_'.$key =>'catalog_product_index_eav'),'at_'.$key.'.entity_id = e.entity_id and at_'.$key.'.attribute_id = '.$codeId.' and at_'.$key.'.store_id = '.Mage::helper('mobile')->getStore()->getId())->where('at_'.$key.'.value = '.$value);
}
}
$collection->setPage($page_no, 10);
foreach($collection as $product){
echo $product->getName();
}