Injecting custom navigation using a View Helper th

2019-06-13 03:43发布

问题:

I'm just starting out developing for Zend Framework 2. I'm trying to add a simple menu to my Application. The menu will eventually be loaded from a database as user-definable bookmarks, so at the moment, I am trying to instantiate a view helper I've defined, add pages programmatically in the controller, and then inject the view helper's navigation into the view model. My problem is that when I try to retrieve my view helper in the controller by using the ServiceLocator, I get a ServiceNotFoundException:

Application\View\Helper\ShortcutsMenu:

    namespace Application\View\Helper;

    use Zend\Navigation\Navigation;

    class ShortcutsMenu extends Navigation {

        public function shortcutsMenu() {
            //...
        }

        public function __construct() {
            //...
        }

    }

and in Module.php

public function getServiceConfig() {
    return array(
        'view_helper' => array(
            'factories' => array(
                'shortcutsmenu' => function($sm) {
                    $smenu = new \Application\View\Helper\ShortcutsMenu();
                    return $smenu;
                }
            ),
        ),
    );

IndexController.php:

    $smenu = $this->getServiceLocator()->get('shortcutsmenu'); // throws ServiceNotFoundException
    //"Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for shortcutsmenu"

    $smenu->addPage(AbstractPage::factory(array(
        'label' => 'Homepage',
        'order' => '-1',
        'uri' => '/',
    )));

    // ...
}

Can anyone tell me what I'm missing?

Edit: The HTML I would like to generate in the application-wide layout would be something like:

<!-- Side tabs shortcuts -->
<ul id="shortcuts">
    <li class="current"><a href="./" class="shortcut-home" title="Home">Home</a></li>
    <li><a href="userpage1.html" title="My messages">My messages</a></li>
    <li><a href="/a/b/c?id=4" title="Bob's calendar">Bob's calendar</a></li>
    <li>...</li>
</ul>

probably using URI-style links rather than MVC ones.

回答1:

There is no need to extend the navigation container Zend\Navigation\Navigation or extend the builtin view helpers to render menu's.

A container manages all pages in the navigation structure. The are several ways to create a container.

All the view helpers (menu, breadcrumbs) use the container as the provider for navigation data. You can eighter set a new container on the view helper using setContainer(). Alternatively you could just call the view helper in your view without a container setup and the view helper will create a new empty container for you.

If you need some alternate rendering because the default view helpers don't provide it you can create you own navigation view helper.

namespace MyNamespace\View\Helper\Navigation;

use Zend\View\Helper\Navigation\AbstractHelper;

class MyHelper extends AbstractHelper
{
}

Next register your view helper to the navigation pluginManager. I think you can do something like this (untested):

class Module
{
    public function onBootstrap($e)
    {
        $application = $e->getApplication();
        /** @var $serviceManager \Zend\ServiceManager\ServiceManager */
        $serviceManager = $application->getServiceManager();

        $pm = $serviceManager->get('ViewHelperManager')->get('Navigation')->getPluginManager();
        $pm->setInvokableClass('myHelper', 'MyNamespace\View\Helper\Navigation\MyHelper');
    }
}

Now call you custom helper in your view:

$this->navigation()->myHelper()