[英]Loading Modules Dynamically in Zend Framework 2
我昨天也问过这个问题,但这个问题包括代码。
我的应用程序有多个模块和两种类型的用户帐户,一些模块always
加载在application.config.php
,其中一些是conditional
即一些加载用户type A
,一些加载用户type B
在浏览Stack Overflow上的文档和问题之后,我了解了一些ModuleManager功能,并开始实现我可能会工作的逻辑。
一些我怎么想出一种方法来加载application.config.php
[SUCCESS]中不存在的模块,但是它们的配置不起作用[问题]即如果在onBootstrap
方法中我获得了ModuleManager
服务并且执行了getLoadedModules()
我获取正确加载的所有模块的列表。 之后如果我尝试从动态加载的模块中获取某些服务,它会抛出异常。
Zend \\ ServiceManager \\ ServiceManager :: get无法获取或创建jobs_mapper的实例
请注意,工厂和所有其他东西都很好,因为如果我从application.config.php加载模块它工作正常
类似地,当我尝试从动态加载的模块访问任何路由时,它会抛出404 Not Found
,这表明即使模块由ModuleManager加载,这些模块的module.config.php配置也没有加载。
在我的Application模块的Module.php中,我实现了InitProviderInterface
并添加了一个方法init(ModuleManager $moduleManager)
,其中我捕获了moduleManager loadModules.post事件触发器并加载了模块
public function init(\Zend\ModuleManager\ModuleManagerInterface $moduleManager)
{
$eventManager = $moduleManager->getEventManager();
$eventManager->attach(\Zend\ModuleManager\ModuleEvent::EVENT_LOAD_MODULES_POST, [$this, 'onLoadModulesPost']);
}
然后在同一个类中,我将方法onLoadModulesPost
并开始加载我的动态模块
public function onLoadModulesPost(\Zend\ModuleManager\ModuleEvent $event)
{
/* @var $serviceManager \Zend\ServiceManager\ServiceManager */
$serviceManager = $event->getParam('ServiceManager');
$configListener = $event->getConfigListener();
$authentication = $serviceManager->get('zfcuser_auth_service');
if ($authentication->getIdentity())
{
$moduleManager = $event->getTarget();
...
...
$loadedModules = $moduleManager->getModules();
$configListener = $event->getConfigListener();
$configuration = $configListener->getMergedConfig(false);
$modules = $modulesMapper->findAll(['is_agency' => 1, 'is_active' => 1]);
foreach ($modules as $module)
{
if (!array_key_exists($module['module_name'], $loadedModules))
{
$loadedModule = $moduleManager->loadModule($module['module_name']);
//Add modules to the modules array from ModuleManager.php
$loadedModules[] = $module['module_name'];
//Get the loaded module
$module = $moduleManager->getModule($module['module_name']);
//If module is loaded succesfully, merge the configs
if (($loadedModule instanceof ConfigProviderInterface) || (is_callable([$loadedModule, 'getConfig'])))
{
$moduleConfig = $module->getConfig();
$configuration = ArrayUtils::merge($configuration, $moduleConfig);
}
}
}
$moduleManager->setModules($loadedModules);
$configListener->setMergedConfig($configuration);
$event->setConfigListener($configListener);
}
}
我认为你在这里尝试做的事情有一些根本性的错误:你正在尝试基于合并配置加载模块,因此在模块和合并配置之间创建循环依赖。
我会建议不要这样做。
相反,如果您有定义要加载应用程序的哪个部分的逻辑,请将其放在config/application.config.php
,该部门负责检索模块列表。
但是在这个阶段,依赖任何服务还为时过早,因为服务定义也依赖于合并的配置。
需要澄清的另一件事是,您正在尝试根据经过身份验证的用户(请求信息,而不是环境信息)是否与特定条件匹配,然后根据该修改整个应用程序来做出这些决策。
不要这样做:相反,通过在其前面放置一个警卫,将决定移动到有条件地启用/禁用的组件中。
你要问的是什么,但这并不意味着你应该这样做。
在不知道您正在构建的应用程序的复杂性的情况下建议适当的解决方案很困难。
使用警卫肯定会帮助解耦你的代码,但是单独使用它并不能解决可扩展性和可维护性问题,如果这是一个问题呢?
我建议使用无状态基于令牌的身份验证。 不是在每个应用程序中维护验证逻辑,而是在一个公共位置编写验证逻辑,以便每个请求都可以使用该逻辑,而不管应用程序如何。 选择反向代理服务器(Nginx)来维护验证逻辑(在Lua的帮助下)使您可以灵活地以任何语言开发应用程序。
更重要的是,在负载均衡器级别验证凭据基本上消除了对会话状态的需要,您可以在多个平台和域上运行许多单独的服务器,重用相同的令牌来验证用户。
识别用户,帐户类型和加载不同的模块然后变成一项微不足道的任务。 只需通过环境变量传递令牌信息,就可以在config/application.config.php
文件中读取它,而无需事先访问数据库,缓存或其他服务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.