Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
329 views
in Technique[技术] by (71.8m points)

config - How to set up 2 navigations in zf2?

I have a config for main navigation link and the second just with 1 link. The main navigation is working fine, but when I try setting up a second navigation bar in module like this:

$config = $e->getApplication()->getServiceManager()->get('config');
$navigation = new endNavigationNavigation($config['navigation_footer']);
$e->getApplication()->getServiceManager()
    ->setService('new_navigation', $navigation);`

I get an error when I render it in the view:

Fatal error: ZendNavigationExceptionDomainException: ZendNavigationPageMvc::getHref cannot execute as no ZendMvcRouterRouteStackInterface instance is composed in /home/cawa/www/sp-app/vendor/zendframework/zendframework/library/Zend/View/Helper/Navigation/AbstractHelper.php on line 471

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem is a missing Router (or to be more precise, a ZendMvcRouterRouteStackInterface). A route stack is a collection of routes and can use a route name to turn that into an url. Basically it accepts a route name and creates an url for you:

$url = $routeStack->assemble('my/route');

This happens inside the MVC Pages of ZendNavigation too. The page has a route parameter and when there is a router available, the page assembles it's own url (or in ZendNavigation terms, an href). If you do not provide the router, it cannot assemble the route and thus throws an exception.

You must inject the router in every page of the navigation:

$navigation = new Navigation($config);
$router     = $serviceLocator->get('router');

function injectRouter($navigation, $router) {
  foreach ($navigation->getPages() as $page) {
    if ($page instanceof MvcPage) {
      $page->setRouter($router);
    }

    if ($page->hasPages()) {
      injectRouter($page, $router);
    }
  }
}

As you see it is a recursive function, injecting the router into every page. Tedious! Therefore there is a factory to do this for you. There are four simple steps to make this happen.

STEP ONE

Put the navigation configuration in your module configuration first. Just as you have a default navigation, you can create a second one secondary.

'navigation' => array(
    'secondary' => array(
        'page-1' => array(
            'label' => 'First page',
            'route' => 'route-1'
        ),
        'page-2' => array(
            'label' => 'Second page',
            'route' => 'route-2'
        ),
    ),
),

You have routes to your first page (route-1) and second page (route-2).

STEP TWO

A factory will convert this into a navigation object structure, you need to create a class for that first. Create a file SecondaryNavigationFactory.php in your MyModule/Navigation/Service directory.

namespace MyModuleNavigationService;

use ZendNavigationServiceDefaultNavigationFactory;

class SecondaryNavigationFactory extends DefaultNavigationFactory
{
    protected function getName()
    {
        return 'secondary';
    }
}

See I put the name secondary here, which is the same as your navigation key.

STEP THREE

You must register this factory to the service manager. Then the factory can do it's work and turn the configuration file into a ZendNavigation object. You can do this in your module.config.php:

'service_manager' => array(
    'factories' => array(
        'secondary_navigation' => 'MyModuleNavigationServiceSecondaryNavigationFactory'
    ),
)

See I made a service secondary_navigation here, where the factory will return a ZendNavigation instance then. If you do now $sm->get('secondary_navigation') you will see that is a ZendNavigationNavigation object.

STEP FOUR

Tell the view helper to use this navigation and not the default one. The navigation view helper accepts a "navigation" parameter where you can state which navigation you want. In this case, the service manager has a service secondary_navigation and that is the one we need.

<?= $this->navigation('secondary_navigation')->menu() ?>

Now you will have the navigation secondary used in this view helper.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...