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();
    }
许可以下: CC-BY-SA归因
scroll top