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.

edigu
  • 9,878
  • 5
  • 57
  • 80

5 Answers5

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);
}
adamdyson
  • 61
  • 1
  • 4
  • 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 ? – Haris Mehmood Jul 24 '17 at 12:27
  • 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? – adamdyson Jul 25 '17 at 13:19
  • Thanks for your reply.I have posted it as a question can u please look into it ? Kind of you https://stackoverflow.com/questions/45295059/loading-modules-dynamically-in-zend-framework-2 – Haris Mehmood Jul 25 '17 at 13:26
  • 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. – adamdyson Jul 25 '17 at 13:44
  • 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); – adamdyson Jul 25 '17 at 16:05
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);
}
STLMikey
  • 1,210
  • 7
  • 19
  • 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. –  Oct 23 '13 at 00:00
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;
}
mellors
  • 31
  • 3
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.

itrascastro
  • 775
  • 6
  • 14
-1

This is better idea.

class module

public function onBootstrap(MvcEvent $e)
{

    $sm = $app->getServiceManager();
    $config = $sm->get('config');

and this is all.

PawelC
  • 43
  • 5