2016-01-05 66 views
2

我有一些Legacy類。 許多類都使用Factory類實例化。將依賴注入容器傳遞給靜態方法

還有一個單身人士班。

未來我想用DIC完全替代它們。 目前代碼庫要做的很大。

現在我的目標是將DI容器注入到由Singleton類實例化的每個服務中。Singleton類有一個帶有這個簽名的靜態方法。

final class Singleton 
{ 
    private static $singletonCache = array(); 

    public static function getInstance($namespace, $className) 
    { 
    } 
} 

這個功能我想,以檢查內部:

$instance = new $className(); 

if($instance instanceof ContainerAwareInterface) 
{ 
    // TODO: how do we get the container here 
    $instance->setContainer($container); 
} 

但我如何能最好地讓我的「單級」,這是僅稱爲靜態內部的容器?

+0

'var_dump($ instance);'並檢查你所得到的。 –

+0

這是虛擬代碼。我知道我到了那裏。 我的問題是在靜態方法「getInstance」的上下文中無法使用$ container。我如何從我的全球範圍注入它? – psren

+0

'$ instance-> setContainer($ container);'在這裏你通過傳遞'$ container'參數來調用方法'setContainer'問問你自己,在使用之前你在哪裏得到它? –

回答

2

某處早在你的啓動代碼,但容器實例化後,您可以在容器傳給你的單例類:

Singleton::setContainer($container); 

這將容器存放在一個靜態屬性:

final class Singleton 
{ 
    // ... 

    private static $container; 

    public static function setContainer(ContainerInterface $container) 
    { 
     self::$container = $container; 
    } 
} 

但是,正如你在單例課程的例子中學到的那樣,所有的全局狀態都給你帶來了麻煩。傳遞容器(並使用ContainerAware)是可以避免的。通過將容器傳遞給你的服務,你使他們依賴於整個服務世界。只有通過你真正需要的合作者才更清潔。測試也容易得多。

+0

我瞭解最佳做法。但在這一刻,我必須保留遺留類,因爲有些客戶依賴它們。我無法控制CodeBase,所以我必須保持BC。這有點難以解釋,但我將在後面重構並擺脫完整的課程。 – psren

+1

經過近兩年的時間,我可以說:這個解決得很好。 我用適當的依賴注入添加了Symfony-DiC。 然後我寫了一個「facade」Container :: get($ id)Container :: getParam($ key)。 用我的代碼替換了所有愚蠢的實例。 Container-Class用於拋棄棄用並將它們記錄到Kibana。方式後來我能夠刪除低劣的代碼:-) 不錯。謝謝。 – psren

4

另一種方法是在全球範圍內訪問容器,當你需要它:

public static function getInstance($namespace, $className) 
{ 
    $container = $_GLOBAL['kernel']->getContainer(); 
} 

當然也有不對的做法各種各樣的事情,但只要你正在轉換那麼它足以讓通過。

+2

這是有風險的,因爲它也允許其他人從$ _GLOBAL訪問容器。在你試圖清理的代碼庫中,你不應該開放新的機會來搞砸。 –

+0

無論全球都在那裏。就像Symfony的設計一樣。開發人員不要濫用它。 – Cerad

+0

我的問題是,有大量的狗屎...... 我試圖讓事情的第一個容器使用全局狀態使用服務容器。 然後我開始拋棄全球使用的廢棄物,並開始將部件重構爲適當的DI。 我很喜歡這個方法,而且我幾乎完成了重構應用程序的工作。 – psren