簡體   English   中英

在Zend Framework 2中動態加載模塊

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM