Documentation seems to be wrong ...
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?
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!
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.
Thanks for the hint!
May I ask you to provide an example how to use a lazy listener which listen on the "render" Event?
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.
Now I get the Picture. Works like a charm, Thanks a lot!
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?
@newmind507 Please provide the complete error message, otherwise we would have to guess.
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
@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)
Module.php(namespace Application), NavigationListener.php(namespace Application\Listener)
Do have also the namespace in your config? The Service Manager says something different in your error message: "Listener\NavigationListener"
'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
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.)
new error http://aquariunm.esy.es/
@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!
http://aquariunm.esy.es/ - still don't want work((
@newmind507 Let's continue at the forum. (I have tested it with the skeleton application without problems.)
This repository has been closed and moved to laminas/laminas-navigation; a new issue has been opened at https://github.com/laminas/laminas-navigation/issues/3.