user3570930
user3570930

Reputation: 51

Dynamically loading ZF2 Modules

I have following application.config

return array(
'modules' => array(

    'Application',
    'ErrorHandler'
),
'module_listener_options' => array(
    'module_paths' => array(
        './module',
        './vendor'
    ),
    'config_glob_paths' => array(
        'config/autoload/{,*.}{global,local}.php'
    )
)
);

and in the Application/Module.php I have (few of the functions):

    public function onBootstrap(MvcEvent $e)
{
    $eventManager        = $e->getApplication()->getEventManager();
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);

    $this->initModules($e);
}

public function getConfig()
{
    return include __DIR__ . '/config/module.config.php';
}

public function getAutoloaderConfig()
{
    return array(
        'Zend\Loader\StandardAutoloader' => array(
            'namespaces' => array(
                __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
            ),
        ),
    );
}

private function getModules(MvcEvent $e) {
    $sm = $e->getApplication()->getServiceManager();
    $moduleTable = $sm->get('ModuleTable');

    $modules = array();

    foreach ($moduleTable->fetchAll() as $m) {
        $modules[] = $m;
    }

    return $modules;
}

private function initModules(MvcEvent $e) {
    $modules = $this->getModules($e);

    $serviceManager = $e->getApplication()->getServiceManager();
    $moduleManager = $serviceManager->get('ModuleManager');

    $loadedModules = $moduleManager->getLoadedModules();

    foreach ($loadedModules as $module) {
        $this->loadedModules[] = str_replace('\Module', '', get_class($module));
    }

    foreach ($modules as $module) {
        try {
            $moduleManager->loadModule($module->getName());
            $this->loadedModules[] = $module->getName();
        } catch (\Exception $e) {
            $this->failedModules[] = $module->getName();
        }
    }

    if (count($this->failedModules) > 0) {
        // Error in loading modules
        exit;
    }

    return $this;
}

public function getServiceConfig()
{
    return array(
        'factories' => array(
            'ModuleTable' =>  function($sm) {
                return new ModuleTable($sm->get('Zend\Db\Adapter\Adapter'));
            },
        ),
    );
}

what I'm trying to achieve here is to have modules dynamically loaded based on a setting from database.

i get no error in loading modules ... when i try calling back $moduleManager->getLoadedModules(); i see that the module is in the loaded list but its config and its functionality doesnt work. Specifically i have routes in that module and when trying to access them i get 404. but if i include the module in the application.config all works perfect.

Possible to achieve? If yes any guidelines?

Thanks

UPDATE

I managed to get the modules dynamically loaded within the Module::init() method ... but without any success accessing the ServiceManager and/or db access to load the list of modules from db ...

Upvotes: 2

Views: 1026

Answers (1)

This is an old question but I saw it today trying to do the exact same thing. My code is geared toward ZF3 but should work on ZF2:

https://github.com/basicinvoices/basicinvoices-modulemanager

The basics I've followed...

  1. Wait until the modules have been loaded (ModuleEvent::EVENT_LOAD_MODULES_POST) this way we have access to the database configuration. I hooked into it with hight priority (9000) to be sure it is runned before other events.
  2. At this point I load a Database adapter. The module services have NOT yet been assigned so we must create it by hand but it is easy. We search for active modules in the database which haven't been loaded yet and we load them with the ModuleManager::loadModule() method. We also add it to the modules array and set it back to the ModuleManager
  3. The config is not merged and, to a certain point that is great as if the config has been cached we would have problems if the module has changed in out database... but it requires an extra step, we should check if the module has a config and, if it does, we shall merge it into the merged config ourselves.

...and that's about it.

Upvotes: 0

Related Questions