This tutorial explains how to render custom menus by using the Zend\Navigation
component.
The behavior is easy to understand. There is a built-in navigation service that consumes a previously set configuration where we define pages and subpages.
'navigation' => [
'navigation-example' => [
[
'label' => 'Google',
'uri' => 'https://www.google.com',
'target' => '_blank'
],
[
'label' => 'Home',
'route' => 'home'
],
[
'label' => 'Modules',
'uri' => '#',
'pages' => [
[
'label' => 'LearnZF2Ajax',
'route' => 'learnZF2Ajax'
],
[
'label' => 'LearnZF2FormUsage',
'route' => 'learn-zf2-form-usage'
],
[
'label' => 'LearnZF2Barcode',
'route' => 'learn-zf2-barcode-usage'
],
[
'label' => 'LearnZF2Pagination',
'route' => 'learn-zf2-pagination'
],
[
'label' => 'LearnZF2Log',
'route' => 'learn-zf2-log'
]
]
]
]
]
The configuration has to be set under the 'navigation' key, and then, under a custom key for certain menu. In this case, our menu is the 'navigation-example' menu.
Finally we just have to define a couple pages and subpages, each one of them with at least a label and a route (to use a previously defined ZF2 route) or uri (to point the page to an absolute URI)
The last step would be to define a factory that can create the Navigation service that will work with this menu. ZF2 comes with a built-in DefaultNavigationFactory
that can create a service which consumes the menu configuration under the key 'default'. If we extend it, we just need to define our custom menu name on the new factory
This could be our factory
namespace LearnZF2Navigation\Navigation;
use Zend\Navigation\Service\DefaultNavigationFactory;
class NavigationFactory extends DefaultNavigationFactory
{
/**
* @return string
*/
protected function getName()
{
return 'navigation-example';
}
}
We just need to register this factory under the name of our menu.
'service_manager' => [
'factories' => [
'navigation-example' => 'LearnZF2Navigation\Navigation\NavigationFactory'
]
]
Now that everything is configured we have to render the menu.
Menus are rendered using the Navigation
view helper. It consumes certain navigation service to render its wrapped menu.
By default it just creates a group of nested unordered lists as you can see in the first part of the demo.
<?php echo $this->navigation('navigation-example')->menu(); ?>
Of course, it is possible to define a custom view partial script so that we can customize the way the menu is rendered. It's the second part of the demo on top of this page.
$this->navigation('navigation-example')->menu()->setPartial('learn-zf2-navigation/partials/navigation');
echo $this->navigation('navigation-example')->menu()->render();
The partial could be like this.
<nav class="navbar navbar-inverse">
<ul class="nav navbar-nav">
<?php foreach ($this->container as $page):
/** @var Zend\Navigation\Page\AbstractPage $page */ ?>
<li class="<?php echo $page->hasPages() ? 'dropdown' : '' ?>">
<a href="<?php echo $page->getHref() ?>" target="<?php echo $page->getTarget() ?>"
<?php echo $page->hasPages() ? 'class="dropdown-toggle" data-toggle="dropdown"' : '' ?>>
<?php echo $page->getLabel() ?>
<?php if ($page->hasPages()): ?>
<span class="caret"></span>
<?php endif; ?>
</a>
<?php if ($page->hasPages()): ?>
<ul class="dropdown-menu">
<?php foreach ($page->getPages() as $child):
/** @var Zend\Navigation\Page\AbstractPage $child */ ?>
<li>
<a href="<?php echo $child->getHref() ?>">
<?php echo $child->getLabel() ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
</nav>
This partial basically renders a Bootstrap navbar by using the injected container
object
The container object is a Zend\Navigation\Navigation
instance that can be iterated to render its wrapped pages. Each page is can have ots own children pages