In my ZF2 application I have a this navigation view script:
$routeMatch = $this->getHelperPluginManager()
->getServiceLocator()
->get('Application')
->getMvcEvent()
->getRouteMatch();
$currentRoute = $routeMatch instanceof \Zend\Mvc\Router\RouteMatch ? $routeMatch->getMatchedRouteName() : null;
?>
<?php foreach ($this->container as $page) : ?>
<li <?php echo $currentRoute == $page->getRoute() ? ' class="active"' : null;?>>
<?php echo $this->navigation()->menu()->htmlify($page, true, false) . PHP_EOL; ?>
</li>
<?php endforeach; ?>
Since the getServiceLocator()
is now deprecated, I need another way to get the information about the current route into the navigation view script.
This view script gets set as partial and called in the layout.phtml
:
echo $this->navigation('navigation')->menu()->setPartial('navigation/default');
So I got the idea to pass the need information via a template variable. I created one in the Module#onDispatch(...)
:
public function onDispatch(MvcEvent $mvcEvent)
{
$viewModel = $mvcEvent->getApplication()->getMvcEvent()->getViewModel();
$routeMatch = $mvcEvent->getRouteMatch();
$viewModel->currentRoute = $routeMatch instanceof RouteMatch
? $routeMatch->getMatchedRouteName() : null
;
}
Now I can access it in the layout.phtml
. But I don't find a way to pass it into the navigation view script, since the Zend\View\Helper\Navigation\Menu#setPartial(...)
` doesn's accept any arguments for variables.
How to pass variables (especially the information about the current route) into the navigation view in Zend Framework 3?
The easiest way to do it using DefaultNavigationFactory
.
Lets say we have some routes as the following
'router' => [
'routes' => [
'world' => [
'type' => Literal::class,
'options' => [
'route' => '/world',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
'may_terminate' => true,
'child_routes' => [
'country' => [
'type' => Literal::class,
'options' => [
'route' => '/country',
'defaults' => [
'controller' => Controller\WorldController::class,
'action' => 'country',
],
],
],
],
],
],
],
Now we would define our navigation configuration under top-level key navigation
and enable zend navigation. You may put this code into your config/autoload/global.php
Depending on the above route configuration our navigation configuration would be like the following
// configure the navigation
'navigation' => [
'default' => [
[
'label' => 'Home',
'route' => 'home',
],
[
'label' => 'World',
'route' => 'world', // this should be the route name not route pattern like '/world'
'pages' => [
[
'label' => 'Country',
'route' => 'world/country',
],
],
],
],
],
// Register the navigation
'service_manager' => [
'factories' => [
'navigation' => Zend\Navigation\Service\DefaultNavigationFactory::class,
],
],
Now we would be able to call the navigation view helper using the top key navigation
from the above configuration into the view script. See below
<div class="collapse navbar-collapse">
<?php
echo $this->navigation('navigation')
->menu()
->setUlClass('nav navbar-nav')
->renderMenu();
?>
</div>
That's it!
The following shows how you can restrict routes to the user and set ACL object or user Role object through the navigation helper's setter methods. Here $this->loggedInUser
, $this->acl
and $this->userRole
has been injected to the view script thus
<div class="collapse navbar-collapse" id="main-menu">
<?php if ($this->loggedInUser !== null) : ?>
<?php $this->navigation('navigation')
->findBy('route', 'hello')
->setParams(array('username' => $this->loggedInUser->getUsername())); ?> // If you need to pass any params
<?php $this->navigation('navigation')
->findBy('route', 'world'); ?>
<?php endif; ?>
<?php
echo $this->navigation('navigation')
->menu()
->setUlClass('nav navbar-nav')
->setAcl($this->acl) // ACL object
->setRole($this->userRole) // Role Object
->renderMenu();
?>
</div>
Hope this would help you!