As you already know the real category filtering is taking place in app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php
, more specifically in _getItemsData()
. Let us inspect that method.
<?php
$categoty = $this->getCategory();
$categories = $categoty->getChildrenCategories();
$this->getLayer()->getProductCollection()
->addCountToCategories($categories);
$data = array();
foreach ($categories as $category) {
if ($category->getIsActive() && $category->getProductCount()) {
$data[] = array(
'label' => Mage::helper('core')->escapeHtml($category->getName()),
'value' => $category->getId(),
'count' => $category->getProductCount(),
);
}
}
As you can see, the method loads child categories of $categoty
in layered navigation filter. That means we need to set this variable to a parent category in level 2 (Every main categories lies in level 2), according to the current category that we stands.
We can achieve this in many ways. In my method, I dig into the codes further and find the exact position where the category is set for layered navigation.
It resides here app/code/core/Mage/Catalog/Model/Layer.php
in getCurrentCategory()
. The method look like this.
<?php
public function getCurrentCategory()
{
$category = $this->getData('current_category');
if (is_null($category)) {
if ($category = Mage::registry('current_category')) {
$this->setData('current_category', $category);
}
else {
$category = Mage::getModel('catalog/category')->load($this->getCurrentStore()->getRootCategoryId());
$this->setData('current_category', $category);
}
}
return $category;
}
In short, it loads the current category to the variable $categoty
(variable that I mentioned in _getItemsData()
) if it set, otherwise loads the root-category
to variable categoty
. Replace this method with this code
<?php
/**
* Retrieve current category model
* If no category found in registry, the root will be taken
*
* @return Mage_Catalog_Model_Category
*/
public function getCurrentCategory()
{
$category = $this->getData('current_category');
if (is_null($category)) {
$category = Mage::registry('current_category');
if ($category) {
/*
* Check whether the current category is in level 2.
* If yes set it as current category.
* Else check for any parent categories with level 2
*/
if($category->getLevel() != 2) {
//gets all parent categories
$parentCategories = Mage::registry('current_category')->getParentCategories();
/*
* If parent categories exist,search for parent categories in level 2.
* If exist set it as current category.
*else set root category as current category.
*/
if(count($parentCategories) > 0)
{
foreach ( $parentCategories as $parentCategory ) {
if($parentCategory->getLevel() == 2 ) {
$category = Mage::getModel('catalog/category')->load($parentCategory->getId());
$this->setData('current_category', $category);
break;
}
}
}
else {
$category = Mage::getModel('catalog/category')->load($this->getCurrentStore()->getRootCategoryId());
$this->setData('current_category', $category);
}
}
else {
$this->setData('current_category', $category);
}
}
else {
$category = Mage::getModel('catalog/category')->load($this->getCurrentStore()->getRootCategoryId());
$this->setData('current_category', $category);
}
}
return $category;
}
What we are doing here is, we get the parent category in level 2 from the current category and set it to $categoty
, so that we can see all child categories in layered navigation.
As I already mentioned, you can achieve it in many ways. All you need to do is to set $categoty
variable with parent category in level 2. Above I have altered the root files. It is not a good practice. You have to create a module that rewrites the model file app/code/core/Mage/Catalog/Model/Layer.php
and then overwrite the method getCurrentCategory()
.
Hope it helps
Layered navigation filters are rendered in catalog/layer/view.phtml template:
<?php foreach ($_filters as $_filter): ?>
<?php if($_filter->getItemsCount()): ?>
<dt><?php echo $this->__($_filter->getName()) ?></dt>
<dd><?php echo $_filter->getHtml() ?></dd>
<?php endif; ?>
Here you can add checks for category and attribute id (replace the code aabove with the code below):
<?php
$_categoryId = $this->getLayer()->getCurrentCategory()->getId();
$_categoryFilters = array(
// top level categories
array(
'categories' => array(5,8,10),
'attributes' => array('color', 'size'),
),
// second level categories
array(
'categories' => array(6, 7, 9, 11),
'attributes' => array('manufacturer'),
),
);
?>
<?php foreach ($_filters as $_filter): ?>
<?php
$_found = false;
foreach ($_categoryFilters as $_categoryFilter) {
if (in_array($_categoryId, $_categoryFilter['categories']) &&
(!($_attribute = $_filter->getAttributeModel()) ||
in_array($_attribute->getAttributeCode(), $_categoryFilter['attributes']))
)
{
$_found = true;
break;
}
}
?>
<?php if($_found && $_filter->getItemsCount()): ?>
<dt><?php echo $this->__($_filter->getName()) ?></dt>
<dd><?php echo $_filter->getHtml() ?></dd>
<?php endif; ?>
Best Answer
Please see
app\code\core\Mage\Catalog\Model\Layer\Filter\Category.php
It gets the categories using method
protected function _getItemsData()
You can change its logic to return required category ID (say 476) when no category.
Example:
find
$categoty = $this->getCategory();
add lines