Question

TL; DR: Comment filtrer plusieurs sélectionner / attributs déroulant (multi-requêtes serait lourd)? Ou utiliser une autre méthode?

Soit un produit sélectionner / attribut déroulant dont les valeurs correspondent à chaque lettre de l'alphabet (en anglais dans ce cas). La première étiquette de option est "A", sa valeur est 1. "B" est 2, "C" est 3, et ainsi de suite:

J'ai cet attribut assigné à contrôler les filtres de navigation en couches. Ainsi, un utilisateur peut cliquer sur le lien pour une valeur spécifique, et il ajoutera ?my_attribute=2 dans les paramètres de la requête, et la liste des produits montre uniquement les produits dont la valeur d'attribut est « B ».

Je voudrais, au contraire, afficher tous les produits qui sa valeur d'attribut est supérieur ou égal à l'option sélectionnée. Ainsi, dans le cas où un utilisateur clique sur le lien « B » dans nav en couches, les résultats seraient tous les produits de « B-Z » (2-26).

La structure URL: ?my_attribute=2&my_attribute_3&my_attribute=4... serait laid et en plus, il ne fonctionne pas, mais l'idée est là. ?my_attribute=2-26 serait évidemment idéal, mais encore une fois, ce n'est pas ce que fait Magento.

Chose curieuse, en utilisant la recherche avancée fournit cette structure d'URL (via le contrôleur de recherche avancée au lieu de nav couches):

?my_attribute%5B%5D=7&my_attribute%5B%5D=8&my_attribute%5B%5D=9&my_attribute%5B%5D=10

Cela ne fait de fournir les résultats escomptés; cependant, cette structure ne fonctionne pas avec la catégorie / pages en couches, seule recherche avancée.

Je suis en train de décider ce qui serait une meilleure voie à ce point; Dois-je abandonner tout intégré l'utilité de la navigation en couches, et réécrire la place collection de produit chargé de bloc de product_list basé sur ma valeur d'attribut? Ou devrais-je adapter certaines fonctionnalités des résultats de recherche avancée pour répondre à mes besoins?

Il semble que ce serait préférable de laisser la fonctionnalité de navigation en couches seul pour que les autres filtres de produits continuent à fonctionner comme prévu; mais il ne semble pas qu'elle permettra des valeurs multiples à partir d'un seul attribut être sélectionnés en même temps. Sinon, une solution de contournement serait d'utiliser un attribut multi-sélection, et si un produit sera affecté « B », il devrait être affecté toutes les options de « B-Z ». Bien que cela fournirait, il est certainement une solution bâclée qui sera de gérer à l'avenir sujette aux erreurs et maladroits les plus grands résultats instantanés (tout fonctionne sans plus de modifications).

Était-ce utile?

La solution

Ce que je l'ai fait dans ce cas était de réécrire le modèle et la ressource correspondante, donc d'abord réécrire la Mage_Catalog_Model_Layer_Filter_Attribute de classe pour être en mesure d'accepter plusieurs valeurs. Dans mon cas, je me sers des virgules comme séparateur, afin que je puisse filtrer comme ?my_attribute=1,2,3

Dans le procédé apply() I parse l'attribut de mettre les différentes valeurs dans un tableau:

  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;
      }

Ensuite, dans le Mage_Catalog_Model_Resource_Eav_Mysql4_Layer_Filter_Attribute vous devez vous assurer que vous êtes en mesure de filtre pour plusieurs valeurs dans votre requête, donc je réécris la méthode suivante comme ceci:

     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;
    }

Autres conseils

  

Voici la navigation en couches avec la collection de produits personnalisés

<?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();
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top