1

I want to add a custom attribute to categories in menu.

If, in Mage_Catalog_Block_Navigation.php in function _renderCategoryMenuItemHtml I transform

$html[] = '<span>'.$this->escapeHtml($category->getName()) . '</span>';

into

$html[] = '<span>' .$category->getBrand()." ".$this->escapeHtml($category->getName()) . '</span>';

It is working. The brand attribute appears on frontend.

How can I do it the correct way by not editing core files?

I created

Mymodule_Block_Catalog_Navigation.php with

class Mymodule_Block_Catalog_Navigation extends Mage_Catalog_Block_Navigation
{//code I should put here
}

and in config.xml

   <global>
    <blocks>
        <catalog>
            <rewrite>
                <navigation>Mymodule_Block_Catalog_Navigation</navigation>
            </rewrite>
        </catalog>
    </blocks>
</global>

And I'm stuck. how should I extend Mage_Catalog_Block_Navigation to add that code?

  • Seams like you are on the right track. You should copy the method _renderCategoryMenuItemHtml from the original class to your class and do your changes in there. – Marius Feb 2 '15 at 14:05
  • @Marius just copy/paste all the _renderCategoryMenuItemHtml? – Claudiu Creanga Feb 2 '15 at 14:06
  • Yep. Copy it. If the method exists in your new class Magento will use it instead of the one in the parent class. – Marius Feb 2 '15 at 14:07
  • @AmitBera I'll write an answer when I clean my code – Claudiu Creanga Feb 2 '15 at 16:21
1

In order to create a custom category attribute and get the custom attribute of a category in your vertical navigation menu ant top menu you have to follow these steps:

First create the custom attribute for categories:

1) Create a file in app/etc/modules called mycompany_customattribute.xml with the following content:

<?xml version="1.0"?>
<config>
    <modules>
        <mycompany_customattribute>
            <active>true</active>
            <codePool>local</codePool>
        </mycompany_customattribute>
    </modules>
</config>

2) In app/code/local/mycompany/customattribute/etc/config.xml (create this path) you should write the following content:

<?xml version="1.0"?>
<config>
    <modules>
        <mycompany_customattribute>
            <version>0.1.0</version>
        </mycompany_customattribute>
    </modules>
    <global>
        <resources>
            <categoryattributes>
                <setup>
                    <module>mycompany_customattribute</module>
                    <class>Mage_Catalog_Model_Resource_Setup</class>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </categoryattributes>
            <categoryattributes_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </categoryattributes_write>
            <categoryattributes_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </categoryattributes_read>
        </resources>
//following code needed only if you want to include it in the navigation too
//this one is for vertical navigation
        <blocks>
            <catalog>
                <rewrite>
                    <navigation>mycompany_customattribute_Block_Catalog_Navigation</navigation>
                </rewrite>
            </catalog>
//this one is for top navigation
            <page>
                <rewrite>
                    <html_topmenu>mycompany_customattribute_Block_Page_Html_Topmenu</html_topmenu>
                </rewrite>
            </page>
        </blocks>
    </global>
</config>

3) In app/code/local/mycompany/customattribute/sql/customattribute/mysql4-install-0.1.0.php (create path) write:

<?php

$installer = $this;

$installer->startSetup();

$installer->addAttribute('catalog_category', 'name_of_custom_attribute', array(
    'type'          => 'text',
    'label'         => 'name_of_custom_attribute',
    'input'         => 'text',
    'group'         => 'General',
    'global'        => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
    'visible'       => true,
    'required'      => false
));

$this->endSetup();
?>

For calling the attribute on the frontend, like on the category page, just write in catalog/category/view.phtml:

<?php echo $this->getCurrentCategory()->getYourattributename(); ?>  

4) If you want to include the custom attribute in vertical menu:

In app/code/local/mycompany/customattribute/Block/Catalog/Navigation.php (create path) write (we extend the class Mage_Catalog_Block_Navigation from navigation.php core file):

<?php 

class mycompany_customattribute_Block_Catalog_Navigation extends Mage_Catalog_Block_Navigation
{

    protected function _renderCategoryMenuItemHtml($category, $level = 0, $isLast = false, $isFirst = false,
        $isOutermost = false, $outermostItemClass = '', $childrenWrapClass = '', $noEventAttributes = false)
    {
        if (!$category->getIsActive()) {
            return '';
        }
        $html = array();

        // get all children
        // If Flat Data enabled then use it but only on frontend
        $flatHelper = Mage::helper('catalog/category_flat');
        if ($flatHelper->isAvailable() && $flatHelper->isBuilt(true) && !Mage::app()->getStore()->isAdmin()) {
            $children = (array)$category->getChildrenNodes();
            $childrenCount = count($children);
        } else {
            $children = $category->getChildren();
            $childrenCount = $children->count();
        }
        $hasChildren = ($children && $childrenCount);

        // select active children
        $activeChildren = array();
        foreach ($children as $child) {
            if ($child->getIsActive()) {
                $activeChildren[] = $child;
            }
        }
        $activeChildrenCount = count($activeChildren);
        $hasActiveChildren = ($activeChildrenCount > 0);

        // prepare list item html classes
        $classes = array();
        $classes[] = 'level' . $level;
        $classes[] = 'nav-' . $this->_getItemPosition($level);
        if ($this->isCategoryActive($category)) {
            $classes[] = 'active';
        }
        $linkClass = '';
        if ($isOutermost && $outermostItemClass) {
            $classes[] = $outermostItemClass;
            $linkClass = ' class="'.$outermostItemClass.'"';
        }
        if ($isFirst) {
            $classes[] = 'first';
        }
        if ($isLast) {
            $classes[] = 'last';
        }
        if ($hasActiveChildren) {
            $classes[] = 'parent';
        }

        // prepare list item attributes
        $attributes = array();
        if (count($classes) > 0) {
            $attributes['class'] = implode(' ', $classes);
        }
        if ($hasActiveChildren && !$noEventAttributes) {
             $attributes['onmouseover'] = 'toggleMenu(this,1)';
             $attributes['onmouseout'] = 'toggleMenu(this,0)';
        }

        // assemble list item with attributes
        $htmlLi = '<li';
        foreach ($attributes as $attrName => $attrValue) {
            $htmlLi .= ' ' . $attrName . '="' . str_replace('"', '\"', $attrValue) . '"';
        }
        $htmlLi .= '>';
        $html[] = $htmlLi;

        $html[] = '<a href="'.$this->getCategoryUrl($category).'"'.$linkClass.'>';
        $html[] = '<span>' .$this->getCategoryAttribute($category)." ".$this->escapeHtml($category->getName()) . '</span>';
//here we made our change
        $html[] = '</a>';

        // render children
        $htmlChildren = '';
        $j = 0;
        foreach ($activeChildren as $child) {
            $htmlChildren .= $this->_renderCategoryMenuItemHtml(
                $child,
                ($level + 1),
                ($j == $activeChildrenCount - 1),
                ($j == 0),
                false,
                $outermostItemClass,
                $childrenWrapClass,
                $noEventAttributes
            );
            $j++;
        }
        if (!empty($htmlChildren)) {
            if ($childrenWrapClass) {
                $html[] = '<div class="' . $childrenWrapClass . '">';
            }
            $html[] = '<ul class="level' . $level . '">';
            $html[] = $htmlChildren;
            $html[] = '</ul>';
            if ($childrenWrapClass) {
                $html[] = '</div>';
            }
        }

        $html[] = '</li>';

        $html = implode("\n", $html);
        return $html;
    }

    public function getCategoryAttribute($category)
    {
        if ($category instanceof Mage_Catalog_Model_Category) {
            $attribute = $category->getAttribute();
        } else {
            $attribute = $this->_getCategoryInstance()->load($category->getId())->getAttribute();
        }

        return $attribute;
    }

}

?>

5) to include it in the top navigation menu:

In app/code/local/mycompany/customattribute/Block/Page/Html/Topmenu.php (create path):

<?php 
class mycompany_customattribute_Block_Page_Html_Topmenu extends Mage_Page_Block_Html_Topmenu 
{
    protected function _getHtml(Varien_Data_Tree_Node $menuTree, $childrenWrapClass)
        {
            $html = '';

            $children = $menuTree->getChildren();
            $parentLevel = $menuTree->getLevel();
            $childLevel = is_null($parentLevel) ? 0 : $parentLevel + 1;

            $counter = 1;
            $childrenCount = $children->count();

            $parentPositionClass = $menuTree->getPositionClass();
            $itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';

            foreach ($children as $child) {

                $child->setLevel($childLevel);
                $child->setIsFirst($counter == 1);
                $child->setIsLast($counter == $childrenCount);
                $child->setPositionClass($itemPositionClassPrefix . $counter);

                $outermostClassCode = '';
                $outermostClass = $menuTree->getOutermostClass();

                if ($childLevel == 0 && $outermostClass) {
                    $outermostClassCode = ' class="' . $outermostClass . '" ';
                    $child->setClass($outermostClass);
                }
                Mage::log($this->_menu, null, 'hammy.log');
                $html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
                $html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>'
                    .$this->_getAttribute($child) . ' ' . $this->escapeHtml($child->getName()) . '</span></a>';//here we made our change

                if ($child->hasChildren()) {
                    if (!empty($childrenWrapClass)) {
                        $html .= '<div class="' . $childrenWrapClass . '">';
                    }
                    $html .= '<ul class="level' . $childLevel . '">';
                    $html .= $this->_getHtml($child, $childrenWrapClass);
                    $html .= '</ul>';

                    if (!empty($childrenWrapClass)) {
                        $html .= '</div>';
                    }
                }
                $html .= '</li>';

                $counter++;
            }

            return $html;
        }
        protected function _getAttribute($category){
            return Mage::getModel('catalog/category')->loadByAttribute('name', $category->getName())->getAttribute();
        }


    }
?>

Hope this helps somebody. If you have issues, leave comments.

  • I'm trying to implement this on Magento 1.9.2.2 but since Mage_Page_Block_Html_Topmenu::_getHtml() is deprecated, I am trying to call Mage::getModel(...)->loadByAttribute('my_attr', $child->getMyAttr())->getAttribute() and I get: Call to a member function getAttribute() on boolean in .../topmenu/renderer.phtml. Not sure how to proceed; I just want to add icons to the menu entries. – Anthony Jun 5 '16 at 23:30
  • Figured it out using: stackoverflow.com/questions/13154736/… – Anthony Jun 6 '16 at 2:53
  • How can we move the new attribute UP in the backend. It is now the last item but needs to be one of the first input fields. Thx – snh_nl Feb 4 '19 at 9:23
0

If people,

Encounter a problem to display the value of the subcategy field, you will need to use this to display your variable.

//load attribute value without loading whole category model
$subcateg=Mage::getResourceModel('catalog/category')->getAttributeRawValue($category->getId(), "categ_menu", Mage::app()->getStore()->getId());

 $html[] = '<span>' . $subcateg. '</span>';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.