动态加载ZF2模块

问题描述 投票:0回答:1

我有以下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'
    )
)
);

在 Application/Module.php 中我有(几个函数):

    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'));
            },
        ),
    );
}

我在这里想要实现的是根据数据库中的设置动态加载模块。

我在加载模块时没有遇到错误...当我尝试回调 $moduleManager->getLoadedModules(); 时我看到该模块位于已加载列表中,但其配置和功能不起作用。具体来说,我在该模块中有路由,当尝试访问它们时,我得到 404。但是如果我将该模块包含在 application.config 中,那么一切都会完美。

有可能实现吗?如果有的话有什么指导方针吗?

谢谢

更新

我设法在 Module::init() 方法中动态加载模块...但没有成功访问 ServiceManager 和/或数据库访问以从数据库加载模块列表...

php zend-framework2 zend-framework-mvc zend-framework-modules
1个回答
0
投票

这是一个老问题,但我今天看到它试图做同样的事情。我的代码适用于 ZF3,但应该适用于 ZF2:

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

我遵循的基础知识...

  1. 等到模块加载完毕(ModuleEvent::EVENT_LOAD_MODULES_POST),这样我们就可以访问数据库配置了。我以高优先级 (9000) 连接到它,以确保它在其他事件之前运行。
  2. 此时我加载了数据库适配器。模块服务尚未分配,因此我们必须手动创建它,但这很容易。我们在数据库中搜索尚未加载的活动模块,并使用
    ModuleManager::loadModule()
    方法加载它们。我们还将其添加到模块数组中并将其设置回
    ModuleManager
  3. 配置没有合并,在某种程度上,就好像配置已经被缓存一样,如果模块在数据库中发生了更改,我们就会遇到问题......但这需要一个额外的步骤,我们应该检查模块是否有一个配置,如果有,我们将自己将其合并到合并的配置中。

...仅此而已。

© www.soinside.com 2019 - 2024. All rights reserved.