3

我昨天也問了這個問題,但是這個包含代碼。在Zend Framework中動態加載模塊2

問題

我的申請已經多個模塊和2種類型的用戶帳戶,某些模塊被加載always其存在於application.config.php它們中的一些conditional即一些已加載的用戶type A和一些對於用戶type B

在閱讀關於堆棧溢出的文檔和問題之後,我理解了一些ModuleManager功能並開始實現我可能會工作的邏輯。

一些我怎麼想出一個辦法來加載不存在於application.config.php[SUCCESS]但其配置不工作[問題]也就是說,如果在onBootstrap方法我得到ModuleManager服務並執行模塊getLoadedModules()我得到正確加載的所有模塊的列表。之後,如果我嘗試從該動態加載的模塊獲取某些服務,則會引發異常。

的Zend \的ServiceManager \的ServiceManager ::得到無法獲取或jobs_mapper創建一個實例

請注意,工廠和所有其他的東西都完全沒有問題,因爲如果我加載模塊從application.config.php它工作正常

同樣,當我試圖從動態加載的模塊,它拋出404 Not Found其中明確提出,從這些模塊的module.config.php配置不加載甚至訪問任何路線日儘管該模塊由ModuleManager加載。

代碼

以我的應用模塊I實施InitProviderInterface並添加的方法init(ModuleManager $moduleManager)的Module.php其中I趕上ModuleManager會loadModules.post事件觸發和加載模塊

public function init(\Zend\ModuleManager\ModuleManagerInterface $moduleManager) 
{ 
    $eventManager = $moduleManager->getEventManager(); 
    $eventManager->attach(\Zend\ModuleManager\ModuleEvent::EVENT_LOAD_MODULES_POST, [$this, 'onLoadModulesPost']); 
} 

然後,在相同的類我delcare方法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); 
    } 
} 

Questi ons

  • 是否有可能實現我所嘗試的?
  • 如果是這樣,最好的方法是什麼?
  • 我在代碼中缺少什麼?
+0

您會概述_why_您是否重發過兩次相同的問題?上一個問題沒有讓你滿意嗎?我很欣賞你已經承認你已經這樣做了,但總的來說,這是最好的避免,因爲它爲志願者創造了工作。 – halfer

回答

3

我認爲你在這裏試圖做的事情有一些根本的錯誤:你試圖根據合併配置加載模塊,因此在模塊和合並配置之間創建一個循環依賴關係。

我會建議不要這樣做。

相反,如果您有定義應用程序的哪一部分的邏輯,請將其放入config/application.config.php,它負責檢索模塊列表。

雖然在這個階段,依賴任何服務還爲時過早,因爲服務定義也依賴於合併配置。

另一件事說明的是,你正在試圖採取取決於是否認證用戶這些決定(請求信息,而不是環境信息)相匹配的一定的標準,然後修改基於整個應用程序。

不要這樣做:相反,將決定移動到要有條件啓用/禁用的組件中,方法是在其前面放置警衛。

+0

非常感謝您的建議,我們已經爲我們的模塊實施了警衛!所以可能我們根本無法做到這一點?即使我們可以強烈建議我們避免它。 –

+0

你*可以*實現它,但應用程序應該是不可變的,而且是一個整體。介紹這種預引導決策會使得一切難以理解/調試。另外,您在這些決定期間不能使用任何服務。 – Ocramius

0

你在問什麼可以做,但這並不意味着你應該。

在不知道要構建的應用程序的複雜性的情況下,提出適當的解決方案很困難。

使用警衛確實有助於解耦您的代碼,但是單獨使用它並不能解決可擴展性和可維護性問題,如果這是一個問題?

我建議使用無狀態令牌的認證。與其在每個應用程序中維護驗證邏輯,不如在一個共同的地方編寫驗證邏輯,以便每個請求都可以使用該邏輯而不考慮應用程序。選擇一個反向代理服務器(Nginx)來維護驗證邏輯(在Lua的幫助下)可以讓你靈活地用任何語言開發你的應用程序。

更重要的是,在負載均衡器級別驗證憑據本質上消除了對會話狀態的需要,您可以擁有許多單獨的服務器,運行在多個平臺和域上,重複使用相同的令牌來驗證用戶。

識別用戶,帳戶類型和加載不同的模塊,然後成爲一項微不足道的任務。只需通過環境變量傳遞令牌信息,即可在您的config/application.config.php文件中讀取令牌信息,而無需事先訪問數據庫,緩存或其他服務。