2011-10-12 85 views
2

可能重複:
Loading multiple versions of the same classPHP的版本類

什麼是安裝不同版本的PHP類的最佳途徑和撥動他們基於配置價值?

這裏是我的情況(使用Zend Framework - 不應該的問題,但可能):

我有2個不同的版本,我想能夠調用Web服務的。我需要使用我的配置文件中的值在它們之間切換。

現在,我有一個充當工廠的類,並根據配置值確定需要返回哪個類的版本。工廠返回的類的兩個版本都擴展了相同的抽象類,所以一旦工廠返回對象,我就可以在其餘代碼中將這兩個版本對待。這似乎沒什麼問題在理論上,但我最終的代碼看起來像這樣在我的工廠類,這似乎並沒有被很好的做法:

require_once APPLICATION_PATH . '/models/Search/SearchModelV' . $this->config->model->version . '.php'; 

$model_class = 'Search_Model_V' . $this->config->model->version; 
return new $model_class(); 

我使用PHP 5.3,所以我已經實現了命名空間。只要將其用於解決方案即可。

+1

研究使用戰略模式。 –

+0

或者也許是工廠模式。 – hakre

+2

請注意,*版本*通常指您的代碼演變中的順序快照。這個問題主要是關於如何使用工廠實現可插拔架構。 – grossvogel

回答

3

我認爲解決方案可能是「工廠」模式。這意味着你有一個靜態函數可以根據參數創建一個合適的對象。這甚至可以在抽象類上實現,因爲您可以在抽象類上聲明和調用靜態方法。

abstract class Search_Model_Abstract { 
    public static function create($version) { 
     $class = 'Search_Model_V' . $version; 

     return new $class; 
    } 
} 

可以再用Search_Model_Abstract::create($this->config->model->version)

注創建合適的對象,這種方法確實也應該處理可能從構造函數拋出的異常,也應檢查$version針對可能的值。

+0

+1您可能想要傳遞配置本身並讓工廠讀取它所關心的設置,因此每一個客戶端代碼都不必知道這個特定設置在配置中的位置。 – grossvogel

+0

@grossvogel是的。 – lonesomeday

2

我認爲你的理論是好的,什麼讓它覺得哈克是你的實現。一些建議。

  1. 使用全局自動加載機制來避免需要遍佈整個位置的文件。如果你不這樣做,你至少可以在將配置值輸入到require_once之前申請(2)。
  2. 在使用之前驗證配置設置。我不知道你的案子有什麼用,但是最好是白名單,以確保你獲得了可接受的價值。
  3. 確保您能夠實例化新對象,並在返回之前正確處理錯誤。
0

理論上你的應用程序不應該關心版本。它只需要使用當前的一個。版本就是這種情況。例如在php中,我們沒有file_get_contents,file_get_contents_v51等。我們只使用當前可用的版本。對於將include_path更改爲「當前」版本或符號鏈接或使用「複製」構建腳本等情況,將爲您完成這項工作。但那不是你的情況。您需要在同一時間有可用的不同實例。我們不是在談論版本,而是「策略」。在這種情況下,不能動態構建文件路徑。你只有選擇在哪裏做動態包含。就我們所說的「相同」類同名(我想是這樣)而言,我個人會選擇使用依賴注入容器,並根據配置值中的「版本」給予容器不同的配置。

例如

$config = array(
'service_v1.0' => array('path' => 'path/to/my/service/v1.0/'); 
'service_v1.1' => array('path' => 'path/to/my/service/v1.1/'); 
); 
$version = 'service_v1.1'; 
DIContainer::create($config[$version]); 

利用上述方案我不關心的依賴(如果有的話)「當前」的服務(例如,不同的服務鍵,不同的存儲等),據我可以描述配置所有這些和注入它們。有關依賴注入的更多詳細信息,請參閱here。 我的兩毛錢關於問題