2013-04-22 119 views
4

我有下面的代碼,在Magento創建一個自定義菜單:Magento的 - 添加自定義屬性導航

<?php 
/** 
* Catalog navigation 
*/ 

class Infortis_Ultimo_Block_Navigation extends Mage_Core_Block_Template 
{ 
    //NEW: 
    protected $_isAccordion = FALSE; 

    protected $_categoryInstance = null; 

    /** 
    * Current category key 
    * 
    * @var string 
    */ 
    protected $_currentCategoryKey; 

    /** 
    * Array of level position counters 
    * 
    * @var array 
    */ 
    protected $_itemLevelPositions = array(); 

    protected function _construct() 
    { 
     $this->addData(array(
      'cache_lifetime' => false, 
      'cache_tags'  => array(Mage_Catalog_Model_Category::CACHE_TAG, Mage_Core_Model_Store_Group::CACHE_TAG), 
     )); 
    } 

    /** 
    * Get Key pieces for caching block content 
    * 
    * @return array 
    */ 
    public function getCacheKeyInfo() 
    { 
     $shortCacheId = array(
      'CATALOG_NAVIGATION', 
      Mage::app()->getStore()->getId(), 
      Mage::getDesign()->getPackageName(), 
      Mage::getDesign()->getTheme('template'), 
      Mage::getSingleton('customer/session')->getCustomerGroupId(), 
      'template' => $this->getTemplate(), 
      'name' => $this->getNameInLayout(), 
      $this->getCurrenCategoryKey() 
     ); 
     $cacheId = $shortCacheId; 

     $shortCacheId = array_values($shortCacheId); 
     $shortCacheId = implode('|', $shortCacheId); 
     $shortCacheId = md5($shortCacheId); 

     $cacheId['category_path'] = $this->getCurrenCategoryKey(); 
     $cacheId['short_cache_id'] = $shortCacheId; 

     return $cacheId; 
    } 

    /** 
    * Get current category key 
    * 
    * @return mixed 
    */ 
    public function getCurrenCategoryKey() 
    { 
     if (!$this->_currentCategoryKey) { 
      $category = Mage::registry('current_category'); 
      if ($category) { 
       $this->_currentCategoryKey = $category->getPath(); 
      } else { 
       $this->_currentCategoryKey = Mage::app()->getStore()->getRootCategoryId(); 
      } 
     } 

     return $this->_currentCategoryKey; 
    } 

    /** 
    * Get catagories of current store 
    * 
    * @return Varien_Data_Tree_Node_Collection 
    */ 
    public function getStoreCategories() 
    { 
     $helper = Mage::helper('catalog/category'); 
     return $helper->getStoreCategories(); 
    } 

    /** 
    * Retrieve child categories of current category 
    * 
    * @return Varien_Data_Tree_Node_Collection 
    */ 
    public function getCurrentChildCategories() 
    { 
     $layer = Mage::getSingleton('catalog/layer'); 
     $category = $layer->getCurrentCategory(); 
     /* @var $category Mage_Catalog_Model_Category */ 
     $categories = $category->getChildrenCategories(); 
     $productCollection = Mage::getResourceModel('catalog/product_collection'); 
     $layer->prepareProductCollection($productCollection); 
     $productCollection->addCountToCategories($categories); 
     return $categories; 
    } 

    /** 
    * Checkin activity of category 
    * 
    * @param Varien_Object $category 
    * @return bool 
    */ 
    public function isCategoryActive($category) 
    { 
     if ($this->getCurrentCategory()) { 
      return in_array($category->getId(), $this->getCurrentCategory()->getPathIds()); 
     } 
     return false; 
    } 

    protected function _getCategoryInstance() 
    { 
     if (is_null($this->_categoryInstance)) { 
      $this->_categoryInstance = Mage::getModel('catalog/category'); 
     } 
     return $this->_categoryInstance; 
    } 

    /** 
    * Get url for category data 
    * 
    * @param Mage_Catalog_Model_Category $category 
    * @return string 
    */ 
    public function getCategoryUrl($category) 
    { 
     if ($category instanceof Mage_Catalog_Model_Category) { 
      $url = $category->getUrl(); 
     } else { 
      $url = $this->_getCategoryInstance() 
       ->setData($category->getData()) 
       ->getUrl(); 
     } 

     return $url; 
    } 

    /** 
    * Return item position representation in menu tree 
    * 
    * @param int $level 
    * @return string 
    */ 
    protected function _getItemPosition($level) 
    { 
     if ($level == 0) { 
      $zeroLevelPosition = isset($this->_itemLevelPositions[$level]) ? $this->_itemLevelPositions[$level] + 1 : 1; 
      $this->_itemLevelPositions = array(); 
      $this->_itemLevelPositions[$level] = $zeroLevelPosition; 
     } elseif (isset($this->_itemLevelPositions[$level])) { 
      $this->_itemLevelPositions[$level]++; 
     } else { 
      $this->_itemLevelPositions[$level] = 1; 
     } 

     $position = array(); 
     for($i = 0; $i <= $level; $i++) { 
      if (isset($this->_itemLevelPositions[$i])) { 
       $position[] = $this->_itemLevelPositions[$i]; 
      } 
     } 
     return implode('-', $position); 
    } 

    /** 
    * Render category to html 
    * 
    * @param Mage_Catalog_Model_Category $category 
    * @param int Nesting level number 
    * @param boolean Whether ot not this item is last, affects list item class 
    * @param boolean Whether ot not this item is first, affects list item class 
    * @param boolean Whether ot not this item is outermost, affects list item class 
    * @param string Extra class of outermost list items 
    * @param string If specified wraps children list in div with this class 
    * @param boolean Whether ot not to add on* attributes to list item 
    * @return string 
    */ 
    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 (Mage::helper('catalog/category_flat')->isEnabled()) { 
      $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'; 
     } 

     //NEW: add special class if level == 1 and menu is not an accordion. 
     if ($this->_isAccordion == FALSE && $level == 1) { 
      $classes[] = 'item'; 
     } 

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

if ($level == 0 && $hasChildren) { 
     $html[] = '<a href="javascript:void(0)"'.$linkClass.'>'; 
     $html[] = '<span>' . $this->escapeHtml($category->getName()) . '</span>'; 
     $html[] = '</a>'; 
} 
else { 
     $html[] = '<a href="'.$this->getCategoryUrl($category).'"'.$linkClass.'>'; 
     $html[] = '<span>' . $this->escapeHtml($category->getName()) . '</span>'; 
     $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)) { 

      //NEW: add opener if menu is used as accordion. 
      if ($this->_isAccordion == TRUE) 
       $html[] = '<span class="opener">&nbsp;</span>'; 

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

    /** 
    * Render category to html 
    * 
    * @deprecated deprecated after 1.4 
    * @param Mage_Catalog_Model_Category $category 
    * @param int Nesting level number 
    * @param boolean Whether ot not this item is last, affects list item class 
    * @return string 
    */ 
    public function drawItem($category, $level = 0, $last = false) 
    { 
     return $this->_renderCategoryMenuItemHtml($category, $level, $last); 
    } 

    /** 
    * Enter description here... 
    * 
    * @return Mage_Catalog_Model_Category 
    */ 
    public function getCurrentCategory() 
    { 
     if (Mage::getSingleton('catalog/layer')) { 
      return Mage::getSingleton('catalog/layer')->getCurrentCategory(); 
     } 
     return false; 
    } 

    /** 
    * Enter description here... 
    * 
    * @return string 
    */ 
    public function getCurrentCategoryPath() 
    { 
     if ($this->getCurrentCategory()) { 
      return explode(',', $this->getCurrentCategory()->getPathInStore()); 
     } 
     return array(); 
    } 

    /** 
    * Enter description here... 
    * 
    * @param Mage_Catalog_Model_Category $category 
    * @return string 
    */ 
    public function drawOpenCategoryItem($category) { 
     $html = ''; 
     if (!$category->getIsActive()) { 
      return $html; 
     } 

     $html.= '<li'; 

     if ($this->isCategoryActive($category)) { 
      $html.= ' class="active"'; 
     } 

     $html.= '>'."\n"; 
     $html.= '<a href="'.$this->getCategoryUrl($category).'"><span>'.$this->htmlEscape($category->getName()).'</span></a>'."\n"; 

     if (in_array($category->getId(), $this->getCurrentCategoryPath())){ 
      $children = $category->getChildren(); 
      $hasChildren = $children && $children->count(); 

      if ($hasChildren) { 
       $htmlChildren = ''; 
       foreach ($children as $child) { 
        $htmlChildren.= $this->drawOpenCategoryItem($child); 
       } 

       if (!empty($htmlChildren)) { 
        $html.= '<ul>'."\n" 
          .$htmlChildren 
          .'</ul>'; 
       } 
      } 
     } 
     $html.= '</li>'."\n"; 
     return $html; 
    } 

    /** 
    * Render categories menu in HTML 
    * 
    * @param bool Add opener if menu is used as accordion. 
    * @param int Level number for list item class to start from 
    * @param string Extra class of outermost list items 
    * @param string If specified wraps children list in div with this class 
    * @return string 
    */ 
    public function renderCategoriesMenuHtml($isAccordion = FALSE, $level = 0, $outermostItemClass = '', $childrenWrapClass = '') 
    { 
     //NEW: save additional attribute 
     $this->_isAccordion = $isAccordion; 

     $activeCategories = array(); 
     foreach ($this->getStoreCategories() as $child) { 
      if ($child->getIsActive()) { 
       $activeCategories[] = $child; 
      } 
     } 
     $activeCategoriesCount = count($activeCategories); 
     $hasActiveCategoriesCount = ($activeCategoriesCount > 0); 

     if (!$hasActiveCategoriesCount) { 
      return ''; 
     } 

     $html = ''; 
     $j = 0; 
     foreach ($activeCategories as $category) { 
      $html .= $this->_renderCategoryMenuItemHtml(
       $category, 
       $level, 
       ($j == $activeCategoriesCount - 1), 
       ($j == 0), 
       true, 
       $outermostItemClass, 
       $childrenWrapClass, 
       true 
      ); 
      $j++; 
     } 

     return $html; 
    } 

} 

我想自定義的類別屬性(menu_label)添加到菜單項。我已經使用這個教程創建了自定義類別屬性http://www.atwix.com/magento/add-category-attribute/

該屬性在管理中顯示正常,我可以將它打印到正常的模板文件中,但無法顯示在此菜單中。

我以爲$ this-> escapeHtml($ category-> getMenuLabel())會做到這一點,但這不會輸出任何東西。

任何想法?

回答

7

你必須考慮一個事實,即Magento在開/關平面類別上的表現不一樣。 我想你可能在你的情況下與平面類別,因爲它應該工作,否則。

(請檢查系統>配置>目錄>目錄>前端領域的「使用平面目錄範疇」,如果它被設置爲「是」,那是你的問題。

爲了解決這個問題此次在「前端」節點添加到您的config.xml:

<events> 
    <catalog_category_flat_loadnodes_before> 
     <observers> 
      <somemodule> 
       <type>singleton</type> 
       <class>somemodule/observer</class> 
       <method>addMenuAttributes</method> 
      </somemodule> 
     </observers> 
    </catalog_category_flat_loadnodes_before> 
</events> 

然後在你的模塊的模型文件夾中創建一個Observer.php(模型文件夾應該在你的config.xml文件中聲明過,偏離航向)

這裏是觀察員代碼:

<?php 
class Somecompany_Somemodule_Model_Observer { 

    public function addMenuAttributes(Varien_Event_Observer $observer) { 
     $observer->getSelect()->columns(
       array('menu_label') 
     ); 
} 

希望這會有所幫助, 鴨舌

+0

感謝的人!!!! – Magefast 2015-04-30 14:41:48

5

您assumtion是不正確的:

$this->escapeHtml($category->getMenuLabel()) 

這假設$類確實是一個分類模型(Mage_Catalog_Model_category)時INFACT它不是,它是一個節點目的。

,如果你看看這裏:

Mage_Catalog_Model_Observer::_addCategoriesToMenu() 

你會發現,其中實際目錄模型用於創建被傳遞到導航程序作爲Varien_Data_Tree_Node數組。 您可以在此處添加自定義屬性,然後在塊內部訪問它。

$categoryData = array(
    'name' => $category->getName(), 
    'id' => $nodeId, 
    'url' => Mage::helper('catalog/category')->getCategoryUrl($category), 
    'is_active' => $this->_isActiveMenuCategory($category), 
    'my_attribute' => $category->getData('my_attribute') 
); 

然後,您就可以訪問您的自定義菜單塊內的屬性:

$child->getData('my_attribute'); 
//$this->escapeHtml($category->getData('my_attribute')) 
+0

試過,但得到了這個錯誤PHP致命錯誤:PHP致命錯誤:調用一個成員函數getData()在272行的Navigation.php中的非對象。可能是非常簡單的事情。我是一個總新手:) – a1anm 2013-04-26 13:54:38