topmenu rendererを使ってMagentoのカテゴリメニューをカスタムする
この記事は公開から 1年以上が経過しています。現在の最新情報との整合性については弊社では一切の責任を負いかねます。
Magentoをカスタマイズしていると、色々な課題に直面します。
その一つがカテゴリメニューのカスタマイズです。
今回はMagento 1.9系から導入された、「topmenu renderer」を使って、独自のメニュー描画処理を行う方法を解説します。
Magentoのカテゴリメニュー描画処理
Magentoのカテゴリメニューは、Mage_Page_Block_Html_Topmenuを用いて描画されています。
左ナビにカテゴリナビを出すようなエクステンションは、このクラスをリライトすることによって、異なるHTML出力を実現していました。
Magento 1.9までの悩み
ただ、この仕組には基本的に悩ましい問題がありました。
それは、BlockクラスにHTMLパーツがハードコードされているため、カスタマイズしにくいという問題です。
テーマ別にマークアップを調整したいと思っても、基本的な処理はBlockクラスに書き込まれているため、テーマ別に実装することができません。
(もちろん独自にカスタマイズすればいいのですが、たいていのサイトではそうなっていません)
つまり、メニューのマークアップカスタマイズは面倒なカスタマイズだったわけです。
Magento 1.9で導入された「topmenu renderer」
この問題を解決するために、1.9以降では、「topmenu renderer」という仕組が導入されました。
1.9系のデフォルトテーマである、RWDテーマのメニュー定義を見ると以下のように書かれています。
<block type="core/text_list" name="top.menu" as="topMenu" translate="label">
<label>Navigation Bar</label>
<block type="page/html_topmenu" name="catalog.topnav" template="page/html/topmenu.phtml">
<block type="page/html_topmenu_renderer" name="catalog.topnav.renderer" template="page/html/topmenu/renderer.phtml"></block>
</block>
</block>
また、Mage_Page_Block_Html_TopmenuのgetHtml()にも以下のように書かれていて、所定の定義を書くことで、Mage_Page_Block_Html_Topmenu_Rendererに描画処理を委ねることができます。
public function getHtml($outermostClass = '', $childrenWrapClass = '') { Mage::dispatchEvent('page_block_html_topmenu_gethtml_before', array( 'menu' => $this->_menu, 'block' => $this )); $this->_menu->setOutermostClass($outermostClass); $this->_menu->setChildrenWrapClass($childrenWrapClass); if ($renderer = $this->getChild('catalog.topnav.renderer')) { $renderer->setMenuTree($this->_menu)->setChildrenWrapClass($childrenWrapClass); $html = $renderer->toHtml(); } else { $html = $this->_getHtml($this->_menu, $childrenWrapClass); } Mage::dispatchEvent('page_block_html_topmenu_gethtml_after', array( 'menu' => $this->_menu, 'html' => $html )); return $html; }
topmenu rendererは、template/page/html/topmenu/renderer.phtmlを使ってカテゴリメニューを描画します。
1.9以降の場合はこのテンプレートをテーマごとにカスタマイズすることで、独自のメニュー表示を実現することができます。
2つのテンプレートを使って別々のメニューを描画する
さて、このtopmenu rendererを応用することで、別々のカテゴリメニューを描画することができます。
例えばレスポンシブテーマを作る際に、PC表示のメニューとスマホ表示のメニューを別にしたい場合、以下のようにレイアウトXMLを定義することで実現できます。
<block type="core/text_list" name="top.menu" as="topMenu" translate="label">
<label>Navigation Bar</label>
<block type="page/html_topmenu" name="catalog.topnav" template="page/html/topmenu.phtml">
<block type="page/html_topmenu_renderer" name="catalog.topnav.renderer" template="page/html/topmenu/renderer.phtml"></block>
</block>
</block>
<block type="core/text_list" name="top.menu.sp" as="topMenuSp" translate="label">
<label>SP Navigation Bar</label>
<block type="page/html_topmenu" name="catalog.topnav.sp" template="page/html/topmenu_sp.phtml">
<block type="page/html_topmenu_renderer" name="catalog.topnav.renderer" template="page/html/topmenu/renderer_sp.phtml"></block>
</block>
</block>
このように定義すると、それぞれ別のテンプレートを使用するため、全く違った構造のテーマを表示することができます。
(ただ、パフォーマンスの面ではあまりおすすめできるものではないので、できれば1つのメニューで完結させたいところです)
また、テンプレート内に静的ブロックを表示することもできます。アイデア次第で様々なカスタマイズができるでしょう。