Attributi di prodotto e meccanica filtraggio
-
16-10-2019 - |
Domanda
TL; DR: come filtri multipli selezionare / attributi discesa (multi-seleziona sarebbe ingombrante)? Oppure utilizzare un metodo diverso?
Si consideri un prodotto selezionare / attributo discesa i cui valori corrispondono a ciascuna lettera dell'alfabeto (inglese in questo caso). etichetta della prima opzione è "A", il suo valore è 1. "B" è 2, "C" è 3, e così via:
Non ho questo attributo assegnato per controllare i filtri di navigazione a strati. Quindi un utente può fare clic sul collegamento per un valore specifico, e si aggiungerà ?my_attribute=2
nei parametri di richiesta, e gli spettacoli lista dei prodotti solo prodotti il ??cui valore di attributo è "B".
Vorrei, invece, visualizzare tutti i prodotti che del valore dell'attributo è maggiore o uguale all'opzione selezionata. Quindi, nel caso in cui un utente fa clic sul collegamento "B" in nav a strati, i risultati sarebbero tutti i prodotti da "B-Z" (2-26).
L'URL struttura: ?my_attribute=2&my_attribute_3&my_attribute=4...
sarebbe brutto e poi non funziona, ma l'idea c'è. ?my_attribute=2-26
sarebbe ovviamente l'ideale, ma ancora una volta, questo non è ciò che fa Magento.
Curiosamente, utilizzando la ricerca avanzata fornisce la struttura degli URL (attraverso il controller ricerca avanzata invece del nav a strati):
?my_attribute%5B%5D=7&my_attribute%5B%5D=8&my_attribute%5B%5D=9&my_attribute%5B%5D=10
Questa effettivamente fornire i risultati sperati; tuttavia, questa struttura non funziona con la categoria / pagine stratificate, solo la ricerca avanzata.
Sto cercando di decidere quale sarebbe stato un percorso migliore, a questo punto; Dovrei abbandonare tutto la collezione di prodotti built-in utilità di navigazione a strati, e invece riscrivere il blocco del product_list
caricato in base alla mia valore di attributo? O devo adattare alcune funzionalità dai risultati di ricerca avanzati per soddisfare le mie esigenze?
Sembra che sarebbe meglio lasciare funzionalità di navigazione a strati da solo in modo che gli altri filtri di prodotto continuano a funzionare come previsto; ma non sembra che permetterà valori multipli da un singolo attributo essere selezionate contemporaneamente. In alternativa, una soluzione potrebbe essere quella di utilizzare un attributo di selezione multipla, e se un prodotto verrebbe assegnato "B", che avrebbe dovuto essere assegnati tutte le opzioni da "B-Z". Anche se questo avrebbe fornito i maggiori risultati immediati (tutto funzionerà senza ulteriori modifiche), è certamente una soluzione sciatta che sarà soggetto a errori e goffo per gestire in futuro.
Soluzione
Quello che ho fatto in questo caso era di riscrivere sia il modello e la risorsa corrispondente, quindi prima riscrivere il Mage_Catalog_Model_Layer_Filter_Attribute
classe per essere in grado di accettare più valori. Nel mio caso, io sto usando le virgole come separatore, in modo da poter filtrare come ?my_attribute=1,2,3
Nel metodo apply()
il parsing l'attributo di mettere i diversi valori in un array:
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;
}
Poi nel file Mage_Catalog_Model_Resource_Eav_Mysql4_Layer_Filter_Attribute
è necessario fare in modo che siano in grado di filtro per più valori nella tua ricerca, così ho riscritto il seguente metodo come questo:
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;
}
Altri suggerimenti
Ecco la navigazione a strati con raccolta del prodotto personalizzato
<?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();
}