2

I need that some code be executed before any MvcEvent::EVENT_BOOTSTRAP listener get execute. Evidently Module::onBootstrap is no an option. I end with the following code:

class Module { function init(\Zend\ModuleManager\ModuleManager $moduleManager) { $moduleManager->getEventManager()->attach( MvcEvent::EVENT_BOOTSTRAP, array(ClassX, 'StaticMethodOfClassX'), 20000); } } 

I don't want have hard code the array(ClassX, 'StaticMethodOfClassX') reference but get it from the service manager. My problem is that I don't know how to get an service manager reference inside the module's init method. Any help? or this is impossible in ZF2 right now? Whatever variant to this schema or opinion will be appreciate too ;)

EDIT:

I will clarify "Evidently Module::onBootstrap is no an option", cos may be is not so trivial ;)

Modules Module::onBootstrap methods are executed when the event MvcEvent::EVENT_BOOTSTRAP is triggered, but the attachment of each module's Module::onBootstrap method to that event depend of the order in which modules were loaded. Due to, the order in which a specific Module::onBootstrap method will be executed depend on what other modules exist and how other modules affect the order in which that specific module will be loaded. Beside, whatever listener attached to the MvcEvent::EVENT_BOOTSTRAP event with priority greater than 1 will be execute before any module Module::onBootstrap method, example the ViewManager::onBootstrap listener. So, to achieve what I want

I need that some code be executed before any MvcEvent::EVENT_BOOTSTRAP listener get execute

modules obBootstrap methods are not an option.

2
  • 1
    Why can't you use onBootstrap? Commented Oct 22, 2013 at 20:55
  • @TimFountain Thanks for the question Tim. I edit my question to explain why not. Thanks again. Commented Oct 23, 2013 at 0:43

5 Answers 5

6

This is a very old post but since no answer has been accepted and I recently needed to achieve the same thing, I thought I'd share my solution.

The reason I needed to access the ServiceManager before the Bootstrap event is triggered, was so I could manipulate the merged configuration with values retrieved from the database.

Problem:

The example found in the Zend documentation shows how to manipulate the merged configuration, but at that particular time the Service manager is empty, making it impossible to retrieve things like database adapters etc.

Solution:

In your module class, implement the interface InitProviderInterface and add the appropriate method.

public function init(ModuleManagerInterface $moduleManager) { $eventManager = $moduleManager->getEventManager(); $eventManager->attach(ModuleEvent::EVENT_LOAD_MODULES_POST, [$this, 'onLoadModulesPost']); } 

The EVENT_LOAD_MODULES_POST event will get invoked after the EVENT_MERGE_CONFIG event but before the EVENT_BOOTSTRAP event is triggered. Also at this particular time the ServiceManager will contain all the factories, invokable classes you're wanting to access.

Your callback method may look something like.

public function onLoadModulesPost(ModuleEvent $event) { /* @var $serviceManager \Zend\ServiceManager\ServiceManager */ $serviceManager = $event->getParam('ServiceManager'); $configListener = $event->getConfigListener(); $configuration = $configListener->getMergedConfig(false); $someService = $serviceManager->get('Your/Custom/Service'); $information = $someService->fetchSomeInformation(); $configuration = array_merge($configuration, $information); $configListener->setMergedConfig($configuration); $event->setConfigListener($configListener); $serviceManager->setAllowOverride(true); $serviceManager->setService('Config', $configuration); $serviceManager->setAllowOverride(false); } 
Sign up to request clarification or add additional context in comments.

5 Comments

Hi adamdyson, I am actully struggling to load the modules the way you suggested, the modules are loaded but their configuration does not seem to work and when I try to go to route of some dynamically loaded module it gives error 404, which tells us the config is not loaded or working properly, any suggestion in this regard ?
Happy to help, but I'll need a bit more information. I tend to tackle these situations by process of elimination, so what have your tried? When following the example I posted, what does the merged configuration look like? Is any module configuration loaded?
Thanks for your reply.I have posted it as a question can u please look into it ? Kind of you stackoverflow.com/questions/45295059/…
Ok, I now realise you're asking a completely different question to what my answer here solved. If I come up with a solution to your question I'll let you know.
Before I look into this further can you first try disabling config and module cache, also add update the service manager: $serviceManager->setAllowOverride(true); $serviceManager->setService('config', $configuration); $serviceManager->setAllowOverride(false);
0

You can get it off the MvcEvent

$locator = $event->getTarget()->getServiceLocator()->get('YourObject') 

If you don't have access to the event, you can set the event as a property on the Module class on bootstrap, and then use it in your init method whenever.

 public function onBootstrap($event) { $this->setMvcEvent($event); } function init(\Zend\ModuleManager\ModuleManager $moduleManager) { $locator = $this->mvc_event->getTarget()->getServiceLocator()->get('YourClass'); $moduleManager->getEventManager()->attach( MvcEvent::EVENT_BOOTSTRAP, array(ClassX, 'StaticMethodOfClassX'), 20000); } 

1 Comment

Thanks for your reply, but pls, read my question, I wrote "Evidently Module::onBootstrap is no an option" and as you know, I can't access the MVCEvent in the Module::init method.
0

Are you using ZfcBase in your application? The AbstractModule has a boostrap method (not onBootstrap) which is executed by this event handler in the init method

$sharedManager->attach('Zend\Mvc\Application', 'bootstrap', function($e) use ($instance, $moduleManager) { $app = $e->getParam('application'); ... $instance->bootstrap($moduleManager, $app); }); 

Of course you can use this approach without ZfcBase.

Then you can implement Zend\ServiceManager\ServiceLocatorAwareInterface:

public function bootstrap(\Zend\ModuleManager\ModuleManager $moduleManager, \Zend\Mvc\ApplicationInterface $app){ $this->setServiceLocator($app->getServiceManager()); parent::bootstrap($moduleManager, $app); } public function setServiceLocator(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator){ $this->_serviceLocator = $serviceLocator; return $this; } public function getServiceLocator(){ return $this->_serviceLocator; } 

Comments

0

Maybe a bit later but hope it will help somebody else. At the init point there is no much services at the Service Manager but you can access it:

public function init(ModuleManager $moduleManager) { $sm = $moduleManager->getEvent()->getParam('ServiceManager'); $applicationConfig = $sm->get('applicationconfig'); var_dump($applicationConfig['modules']); } 

In this case we are retrieving the module names.

Comments

-1

This is better idea.

class module

public function onBootstrap(MvcEvent $e) { $sm = $app->getServiceManager(); $config = $sm->get('config'); 

and this is all.

Comments