Hmm
This is more of a reminder to ::self than a post. Because it took me nearly a full day to figure out how to be able to put just a logo image in the menu with Zend_View_Helper_Navigation_Menu. So here goes.Note 1: I used ZF 1.11
Note 2: For simplicity, I used "fullmoon" where you should use your application name. Take notice of case within the code, it's important and it changes depending on the part of code you're in.
Step 1: Extend Zend_View_Helper_Navigation_Menu
In the library, create your own menu view helper:library/Fullmoon/View/Helper/Navigation/FullmoonMenu.phpwith the following code:
class Fullmoon_View_Helper_Navigation_FullmoonMenu extends Zend_View_Helper_Navigation_Menu { public function fullmoonMenu(Zend_Navigation_Container $container = null) { return $this->menu($container); } }
Step 2: Modify the layout view script
This will allow you to make the following call in your layout view script (application/layouts/scripts/layout.phtml
):
echo $this->navigation()->fullmoonMenu();
Step 3: Modify the bootstrap
Inapplication/bootstrap.php
, add the following:
/** * Menu */ protected function _initNavigation() { // Load menu data from XML file. First argument is the XML file, // second is the XML node containing the menu XML data $config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav'); // Retrieve the view object $view = $this->getResource('view'); // Add our own Navigation Menu helper to the view plugins path $view->addHelperPath( 'Fullmoon/View/Helper/Navigation', 'Fullmoon_View_Helper_Navigation_' ); // Load the menu into the view $view->navigation(new Zend_Navigation($config)); }Note: You can find examples of XML menu files here.
At this point, your menu should be loading normally, albeit still without an image.
Step 4: Adding the image (aahh, finally!)
Adding the image to the XML file:<img> <class>title</class> <src>/img/logo-small.png</src> <module>default</module> <controller>index</controller> <action>index</action> </img>
Step 5: Amending your menu helper
As a final step, we need to render the image (inlibrary/Fullmoon/View/Helper/Navigation/FullmoonMenu.php
) by overriding the protected _renderMenu()
method from library/Zend/View/Helper/Navigation/Menu.php
:
/** * Renders a normal menu (called from {@link renderMenu()}) * * @param Zend_Navigation_Container $container container to render * @param string $ulClass CSS class for first UL * @param string $indent initial indentation * @param int|null $minDepth minimum depth * @param int|null $maxDepth maximum depth * @param bool $onlyActive render only active branch? * @return string */ protected function _renderMenu(Zend_Navigation_Container $container, $ulClass, $indent, $minDepth, $maxDepth, $onlyActive) { $html = ''; // find deepest active if ($found = $this->findActive($container, $minDepth, $maxDepth)) { $foundPage = $found['page']; $foundDepth = $found['depth']; } else { $foundPage = null; } // create iterator $iterator = new RecursiveIteratorIterator($container, RecursiveIteratorIterator::SELF_FIRST); if (is_int($maxDepth)) { $iterator->setMaxDepth($maxDepth); } // iterate container $prevDepth = -1; foreach ($iterator as $page) { $depth = $iterator->getDepth(); $isActive = $page->isActive(true); if ($depth < $minDepth || !$this->accept($page)) { // page is below minDepth or not accepted by acl/visibilty continue; } else if ($onlyActive && !$isActive) { // page is not active itself, but might be in the active branch $accept = false; if ($foundPage) { if ($foundPage->hasPage($page)) { // accept if page is a direct child of the active page $accept = true; } else if ($foundPage->getParent()->hasPage($page)) { // page is a sibling of the active page... if (!$foundPage->hasPages() || is_int($maxDepth) && $foundDepth + 1 > $maxDepth) { // accept if active page has no children, or the // children are too deep to be rendered $accept = true; } } } if (!$accept) { continue; } } // make sure indentation is correct $depth -= $minDepth; $myIndent = $indent . str_repeat(' ', $depth); if ($depth > $prevDepth) { // start new ul tag if ($ulClass && $depth == 0) { $ulClass = ' class="' . $ulClass . '"'; } else { $ulClass = ''; } $html .= $myIndent . '<ul' . $ulClass . '>' . self::EOL; } else if ($prevDepth > $depth) { // close li/ul tags until we're at current depth for ($i = $prevDepth; $i > $depth; $i--) { $ind = $indent . str_repeat(' ', $i); $html .= $ind . ' </li>' . self::EOL; $html .= $ind . '</ul>' . self::EOL; } // close previous li tag $html .= $myIndent . ' </li>' . self::EOL; } else { // close previous li tag $html .= $myIndent . ' </li>' . self::EOL; } // Manage menu image if ($page->src != '') { $html .= $myIndent . ' <li class="title">' . self::EOL . ' <img src="' . $page->src . '" />' . self::EOL; } else { // render li tag and page $liClass = $isActive ? ' class="active"' : ''; $html .= $myIndent . ' <li' . $liClass . '>' . self::EOL . $myIndent . ' ' . $this->htmlify($page) . self::EOL; } // store as previous depth for next iteration $prevDepth = $depth; } if ($html) { // done iterating container; close open ul/li tags for ($i = $prevDepth+1; $i > 0; $i--) { $myIndent = $indent . str_repeat(' ', $i-1); $html .= $myIndent . ' </li>' . self::EOL . $myIndent . '</ul>' . self::EOL; } $html = rtrim($html, self::EOL); } return $html; }This part is what does the trick:
// Manage menu image if ($page->src != '') { $html .= $myIndent . ' <li class="title">' . self::EOL . ' <img src="' . $page->src . '" />' . self::EOL; } else { // render li tag and page $liClass = $isActive ? ' class="active"' : ''; $html .= $myIndent . ' <li' . $liClass . '>' . self::EOL . $myIndent . ' ' . $this->htmlify($page) . self::EOL; }
Conclusion
I had a hard time gathering the necessary information over the Internet, hopefully this may help out those wanting to add a logo to the menu with Zend Framework.Note that the logo does not have link attached to it, but with a little tweaking of the last code snippet that shouldn't be too difficult ;)
There may be a far simpler solution to this but I don't know of it nor have I found it on the Internet.