Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Documentation seems to be wrong ... #55

Open
ksba opened this issue Dec 23, 2016 · 18 comments
Open

Documentation seems to be wrong ... #55

ksba opened this issue Dec 23, 2016 · 18 comments

Comments

@ksba
Copy link

ksba commented Dec 23, 2016

I found this code snippet in den documenation for the zend-navigation component (ZF3):

Docs » Reference » View Helpers » Intro

The Code snippet provided is not working for me:

<?php
// module/MyModule/Module.php

namespace MyModule;

use Zend\View\HelperPluginManager;
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\GenericRole;
use Zend\Permissions\Acl\Resource\GenericResource;

class Module
{
    /* ... */
    public function getViewHelperConfig()
    {
        return [
            'factories' => [
                // This will overwrite the native navigation helper
                'navigation' => function(HelperPluginManager $pm) {
                    // Setup ACL:
                    $acl = new Acl();
                    $acl->addRole(new GenericRole('member'));
                    $acl->addRole(new GenericRole('admin'));
                    $acl->addResource(new GenericResource('mvc:admin'));
                    $acl->addResource(new GenericResource('mvc:community.account'));
                    $acl->allow('member', 'mvc:community.account');
                    $acl->allow('admin', null);

                    // Get an instance of the proxy helper
                    $navigation = $pm->get('Zend\View\Helper\Navigation');

                    // Store ACL and role in the proxy helper:
                    $navigation->setAcl($acl);
                    $navigation->setRole('member');

                    // Return the new navigation helper instance
                    return $navigation;
                }
            ]
        ];
    }
    /* ... */
}

First it seems that in ZF3 the HelperPluginManager is not passed to the closure. Instead, I found out that the parent ServiceManager is passed.

If I change it to the code below, then the example is working for me:

class Module
{
    /* ... */
    public function getViewHelperConfig()
    {
        return [
            'factories' => [
                // This will overwrite the native navigation helper
                Helper\Navigation::class => function(\Zend\ServiceManager\ServiceLocatorInterface $serviceManager)
                {
                    $navigationViewHelper = new \Zend\View\Helper\Navigation();
                    $navigationViewHelper->setServiceLocator($serviceManager);

                    // Store ACL and role in the proxy helper:
                    $navigationViewHelper->setAcl($this->acl);
                    $navigationViewHelper->setRole($this->role);

                    // Return the new navigation helper instance
                    return $navigationViewHelper;
                }
            ]
        ];
    }
    /* ... */
}

Am I right? Is the documentation for ZF3 not correct?

@froschdesign
Copy link
Member

Am I right? Is the documentation for ZF3 not correct?

You are right. The documentation for ZF3 is wrong, because the Plugin Managers in version 3 of zend-servicemanager have changed.

Thanks for reporting!

@froschdesign
Copy link
Member

Btw. there is no need to override the view helper configuration. A (lazy) listener, which listen on the Zend\Mvc\MvcEvent::EVENT_RENDER is a better choice. The navigation is not required on every request.

@ksba
Copy link
Author

ksba commented Jan 9, 2017

Thanks for the hint!

May I ask you to provide an example how to use a lazy listener which listen on the "render" Event?

@froschdesign
Copy link
Member

froschdesign commented Jan 9, 2017

May I ask you to provide an example how to use a lazy listener which listen on the "render" Event?

The example uses zend-navigation as module.

config/application.config.php:

return [
    'modules' => [
        'Zend\Navigation',
        // …
    ],
];

config/autoload/global.php:

return [
    'event_manager'   => [
        'lazy_listeners' => [
            [
                'listener' => MyModule\Listener\NavigationListener::class,
                'method'   => 'addAcl',
                'event'    => Zend\Mvc\MvcEvent::EVENT_RENDER,
                'priority' => -100,
            ],
        ],
    ],
];

module/MyModule/src/MyModule/Listener/NavigationListener.php

namespace MyModule\Listener;

use Zend\Mvc\MvcEvent;

class NavigationListener
{
    /**
     * @param MvcEvent $event
     */
    public function addAcl(MvcEvent $event)
    {
        // Get service manager
        $serviceManager = $event->getApplication()->getServiceManager();

        // Get view helper plugin manager
        /** @var \Zend\View\HelperPluginManager $helperPluginManager */
        $helperPluginManager = $serviceManager->get('ViewHelperManager');

        // Get navigation plugin
        /** @var \Zend\View\Helper\Navigation $plugin */
        $plugin = $helperPluginManager->get('navigation');

        // Fetch ACL and role from service manager or identity (authentication service)
        // …

        $plugin->setAcl($acl);
        $plugin->setRole($role);
    }
}

At the moment, there is no factory for Event manager and (lazy) listeners. Therefore, we use the module class in this short example.

module/MyModule/Module.php:

namespace MyModule;

use Zend\EventManager\EventInterface;
use Zend\EventManager\LazyListenerAggregate;
use Zend\ModuleManager\Feature\BootstrapListenerInterface;

class Module implements BootstrapListenerInterface
{
    /**
     * @inheritdoc
     */
    public function onBootstrap(EventInterface $e)
    {
        /** @var \Zend\Mvc\MvcEvent $e */

        $application = $e->getApplication();

        /** @var array $config */
        $config = $application->getServiceManager()->get('config');

        if (array_key_exists('event_manager', $config)
            && is_array($config['event_manager'])
            && array_key_exists('lazy_listeners', $config['event_manager'])
        ) {
            $aggregate = new LazyListenerAggregate(
                $config['event_manager']['lazy_listeners'],
                $application->getServiceManager()
            );
            $aggregate->attach($application->getEventManager());
        }
    }
}

Added benefit: you can add more listeners in your config.

@ksba
Copy link
Author

ksba commented Jan 16, 2017

Now I get the Picture. Works like a charm, Thanks a lot!

@froschdesign froschdesign added this to the 2.8.2 milestone Feb 22, 2017
@froschdesign froschdesign removed this from the 2.8.2 milestone May 30, 2018
@newmind507
Copy link

Hi, I add code that written under but get 500 errror in this line $aggregate->attach($application->getEventManager()); .
$aggregate - object(Zend\EventManager\LazyListenerAggregate)#166 (4)
$application->getEventManager() - object(Zend\EventManager\EventManager)#74 (4)
but whan try to attach get 500 error. Can help me somebody?

@froschdesign
Copy link
Member

@newmind507
Please provide the complete error message, otherwise we would have to guess.

@newmind507
Copy link

Fatal error: Uncaught Zend\ServiceManager\Exception\ServiceNotFoundException: Unable to resolve service "Listener\NavigationListener" to a factory; are you certain you provided it during configuration? in /home/u850051480/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:681 Stack trace: #0 /home/u850051480/vendor/zendframework/zend-servicemanager/src/ServiceManager.php(757): Zend\ServiceManager\ServiceManager->getFactory('Listener\Naviga...') #1 /home/u850051480/vendor/zendframework/zend-servicemanager/src/ServiceManager.php(200): Zend\ServiceManager\ServiceManager->doCreate('Listener\Naviga...') #2 /home/u850051480/vendor/zendframework/zend-eventmanager/src/LazyListener.php(119): Zend\ServiceManager\ServiceManager->get('Listener\Naviga...') #3 /home/u850051480/vendor/zendframework/zend-eventmanager/src/LazyListener.php(98): Zend\EventManager\LazyListener->fetchListener() #4 /home/u850051480/vendor/zendframework/zend-eventmanager/src/EventManager.php(322): Zend\EventManager\LazyListener->__invoke(Object( in /home/u850051480/vendor/zendframework/zend-servicemanager/src/ServiceManager.php on line 681

@froschdesign
Copy link
Member

@newmind507
Please recheck the namespace of your listener and the module class. I have updated to code example, because an error was included. (Application vs. MyModule)

@newmind507
Copy link

Module.php(namespace Application), NavigationListener.php(namespace Application\Listener)

@froschdesign
Copy link
Member

Do have also the namespace in your config? The Service Manager says something different in your error message: "Listener\NavigationListener"

@newmind507
Copy link

newmind507 commented Jun 30, 2018

'event_manager'   => [
    'lazy_listeners' => [
        [
            'listener' => Application\Listener\NavigationListener::class,
            'method'   => 'addAcl',
            'event'    => Zend\Mvc\MvcEvent::EVENT_RENDER,
            'priority' => -100,
        ],
    ],
],

http://aquariunm.esy.es/ - error here

@froschdesign
Copy link
Member

froschdesign commented Jun 30, 2018

Add the listener to your service-manager configuration.

module/Application/config/module.config.php:

'service_manager'    => [
	'factories' => [
		Application\Listener\NavigationListener::class => Zend\ServiceManager\Factory\InvokableFactory::class,
	],
],

(I'm sorry, at the moment I can not test this behaviour in an application. I'm on the road.)

@newmind507
Copy link

new error http://aquariunm.esy.es/

@froschdesign
Copy link
Member

froschdesign commented Jun 30, 2018

@newmind507
Very simple: add ::class add the end! (see my code example)

Btw. if you need some more support, then please use the forum or the chat. Thanks!

@newmind507
Copy link

http://aquariunm.esy.es/ - still don't want work((

@froschdesign
Copy link
Member

@newmind507
Let's continue at the forum. (I have tested it with the skeleton application without problems.)

@weierophinney
Copy link
Member

This repository has been closed and moved to laminas/laminas-navigation; a new issue has been opened at laminas/laminas-navigation#3.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants