ZF2 ServiceManager Custom ViewHelpers

The previous article explains how the ‘Zend\Mvc\Service\ModuleManagerFactory‘ sets initializers that gather information from certain keys in the configuration. A ‘ViewHelperManager’ is configured to read the ‘view_helpers’ key. Which expects regular ServiceConfiguration config.

We have seen that the Mvc  ‘ServiceListenerFactory‘ maps the default ‘ViewHelperManager’ to ‘Zend\Mvc\Service\ViewHelperManagerFactory‘. This class does not only have a default helper map, which includes a HelperConfig that will add a factory under the ‘navigation’ key, but also extends from ‘Zend\View\HelperPluginManager‘, which in turn contains the configuration for more ViewHelpers.

And it doesn’t stop there.

The Navigation ViewHelper has it’s own PluginManager to render menus, breadcrumbs, links and sitemaps. I configured my custom Navigation ViewHelper via the app config, and passed a custom configuration to it’s PluginManager.

namespace Ctrl\View\Helper\Navigation;

use Zend\View\Helper\Navigation as ZendNavigation;

class Navigation extends ZendNavigation
{
    protected $defaultPluginMap = array(
        'invokables' => array(
            'menu' => 'Ctrl\View\Helper\Navigation\Menu'
        )
    );

    public function getPluginManager()
    {
        if (null === $this->plugins) {
            $this->setPluginManager(new PluginManager(new \Zend\ServiceManager\Config(
                $this->defaultPluginMap
            )));
        }
        return $this->plugins;
    }

I added a config array and used that to construct the PluginManager, that will override its default Menu ViewHelper. I added the configuration here because I was overriding more stuff in the Navigation class anyway, but this is not necessarily needed. Because we now know exactly where to find our ViewHelper and how it is constructed, we can easily retrieve and manipulate it, for instance, on bootstrap.

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

        /** @var $plugins \Zend\ServiceManager\ServiceManager */
        $plugins = $serviceManager->get('ViewHelperManager')->get('Navigation')->getPluginManager();
        $plugins->get('menu'); //Zend\View\Helper\Navigation\Menu
        $plugins->setInvokableClass('Menu', 'Ctrl\View\Helper\Navigation\Menu');
        $plugins->get('menu'); //Ctrl\View\Helper\Navigation\Menu
    }
}