Best place to add filters to product collection programmatically is
Mage_Catalog_Model_Layer::prepareProductCollection()
not phtml template.
At the moment catalog/product/list.phtml
is rendered, product collection is already loaded and if you don't plan to render products it is better not to load them at all.
The logic should sound like:
public function prepareProductCollection($collection)
{
$collection
->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->addUrlRewrite($this->getCurrentCategory()->getId());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);
// your custom filter
if ($this->_areFiltersApplied()) {
$this->_addInStockFilter($collection);
}
return $this;
}
protected function _areFiltersApplied() {
return count($this->getState()->getFilters()) > 0;
}
protected function _addInStockFilter($collection) {
Mage::getModel('cataloginventory/stock_status')->addIsInStockFilterToCollection($collection);
}
To show filters all time in layered navigation, I have rewritten the magento catalog core classes,
For Attribute Filters,
rewrite class Mage_Catalog_Model_Resource_Layer_Filter_Attribute
,
replace the following line at applyFilterToCollection
function
$tableAlias = $attribute->getAttributeCode() . '_idx';
by,
$tableAlias = $attribute->getAttributeCode() . '_idx_'.$value;
rewrite the Mage_Catalog_Model_Layer_Filter_Attribute
,
Comment Out the $this->_items = array();
at the function apply
,
public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
{
$filter = $request->getParam($this->_requestVar);
if (is_array($filter)) {
return $this;
}
$text = $this->_getOptionText($filter);
if ($filter && strlen($text)) {
$this->_getResource()->applyFilterToCollection($this, $filter);
$this->getLayer()->getState()->addFilter($this->_createItem($text, $filter));
//$this->_items = array();
}
return $this;
}
rewrite the Mage_Catalog_Model_Layer_Filter_Item
to add the following method,
public function isSelected(){
$selected = Mage::getSingleton('core/app')->getRequest()->getParam($this->getFilter()->getRequestVar());
if($selected == $this->getValue()){
return true;
}else{
return false;
}
}
isSelected()
used for getting attribute clear url at the filter.phtml
The above steps will help to show all attributes at all time.
Ref:https://dhimandey.wordpress.com/2012/11/27/show-all-attributes-after-filter-in-layered-navigation/
For Price Filter,
rewrite the Mage_Catalog_Model_Layer_Filter_Price
,
comment out the else
condition at the _getItemsData
protected function _getItemsData()
{
if (Mage::app()->getStore()->getConfig(self::XML_PATH_RANGE_CALCULATION) == self::RANGE_CALCULATION_IMPROVED) {
return $this->_getCalculatedItemsData();
} /*elseif ($this->getInterval()) {
//return array();
}*/
$range = $this->getPriceRange();
$dbRanges = $this->getRangeItemCounts($range);
$data = array();
if (!empty($dbRanges)) {
$lastIndex = array_keys($dbRanges);
$lastIndex = $lastIndex[count($lastIndex) - 1];
foreach ($dbRanges as $index => $count) {
$fromPrice = ($index == 1) ? '' : (($index - 1) * $range);
$toPrice = ($index == $lastIndex) ? '' : ($index * $range);
$data[] = array(
'label' => $this->_renderRangeLabel($fromPrice, $toPrice),
'value' => $fromPrice . '-' . $toPrice,
'count' => $count,
);
}
}
return $data;
}
This will helps to retain the price filter at all time. I hope this answer will help someone.
Best Answer
So you want to remove all filters from your URL. The block that does that is
Mage_Catalog_Block_Layer_State
with the methodwhich in turn uses
So it iterates over all set filters and unsets them in the query. You could do it exactly like this also from the filter block. Or you can try to access the state block and call the getCleanUrl() method.