快速啟動Symfony的 ​​直接投資(依賴注入)教程

史蒂芬勞埃德沃特金斯 ,星期六2010年8月14日下午2時21分

什麼是依賴注入 (直接投資)?

依賴注入是一種技術,允許松耦合對象在一個軟件應用程序。 一般來說,如果一個對象需要訪問它的功能將是另一個實例化內部導致緊耦合系統。 通過實施依賴注入注入所需的對象,我們準備使用(有時也稱為控制反轉 - 國際奧委會)。 看看下面的例子:

  <?PHP的
類決策者 {
    公共職能 makeDecision(數組 $參數){
         / /需要的數據庫適配器
        新DecisionParameters的DP = $();
         = $ $ parameterScore的DP -> getScore($參數);
         / * ... 一些更多的決策邏輯 ...  * /
        返回($ parameterScore“50);
     }
 } 

這件作品的代碼被認為是緊耦合到DecisionParameters對象。 重寫上述在松耦合的方式,我們會碰到這樣的...。

  <?PHP的
類決策者 {
    私人$ _dp;
    公共職能號 function __construct($ DP)的{
         $這個 -> _dp = $ DP的;
     }
    公共職能 makeDecision(數組 $參數){
         $ parameterScore = $此-> _dp -> getScore($參數);
         / * ... 一些更多的決策邏輯 ...  * /
        返回($ parameterScore“50);
     }
 } 

雖然獲得的好處松耦合的代碼,我們正在增加複雜性等,每一次實例化一個對象實例化,我們也有它的依賴,並通過這些了。 例如,這:

 新決策者選擇 = $();
迴聲 $選擇 -> makeDecision(陣列('努力'=>“'低','回'=>”'高')); 

現在變成了:

 新DecisionParameters的DP = $();
新決策者選擇 = $($ DP)的;
迴聲 $選擇 -> makeDecision(陣列('努力'=>“'低','回'=>”'高')); 

這種情況變得更痛苦的人數為一類的依賴增加,而如果依賴本身的依賴性? 這可能很快成為一個對象管理的惡夢! 輸入依賴注入容器(或框架)...

依賴注入容器/框架

依賴注入容器(或框架)辦理對象的創建過程中,實例化和依賴注入任何一個實例,然後返回給調用者。

在您的代碼,而不是直接創建新的對象,我們要求的一個副本對象從 DI容器。 返回的對象,我們已經有了所有依賴注入和對象已經準備就緒。

Symfony的 ​​依賴注入容器

Symfony是最有名的為他們的全棧的MVC框架,但是,他們還推出了一個數量的組件可以獨立使用。 例如,依賴注入容器中,我們將要談論在這裡,一個YAML的分析器,一個模板引擎,見Symfony的 ​​成分更多。

symfony的​​DI容器是基於,從Spring框架的Java

自舉

為了引導 symfony的依賴注入框架,我們使用代碼如下。 我選擇使用的YAML只是因為它容易閱讀和設置。 為了獲得最大的速度你可以寫你的容器,以普通的PHP (symfony的 ​​容器可以為你做一次設置),或者使用緩存整個容器調用Zend_Cache或類似的。

要安裝Symfony的 ​​直接投資按照說明這裡包括http://components.symfony-project.org/dependency-injection/installation ,並把它添加到路徑中。

  / /加載 Symfony的DI容器
需要'sfServiceContainerBuilder.php';
新sfServiceContainerBuilder集裝箱 = $();
新sfServiceContainerLoaderFileYaml裝載機 = $($容器);
 $裝載機>負載(APPLICATION_PATH。'/配置/診斷 / services.yml'); 

首先,我們實例化一個新的容器,然後我們加載我們的配置從一個 YAML文件。 注意:加載配置的DI容器可以從多種格式,如XML的 ,YAML中,PHP中,和INI *. 我傾向於包含一個 YAML文件及其他文件導入從那裡。

多個配置文件可以導入使用不同的格式,較新的定義覆蓋那些已經被定義。 配置文件可以包括對對象的引用和參數。

*的INI只能夠定義參數,不能導入其他文件

配置舉例

 進口:
 - {資源:daos.yml}

參數:
用戶名:假

服務:
 #客戶模型
 model.customer:
等級:Pro_Customer
電話:
 - [setLogger,[@ utils.logger]]
 - [setDao,[@ data.userdata.mysql]]
       - [setUserName,[%用戶名%]]

產品型號#
 model.product:
等級:Pro_Product
    參數:[%用戶名%,{類型:%accesslevel%,lastlogin:%lastlogin%}]
電話:
 - [setDao,[@ data.product.mysql]]

 #記錄儀
 utils.logger:
等級:Pro_Logger
    構造:的getInstance
電話:
 - [setHandle,[@ utils.filewriter]] 

我認為上面的代碼是相當明確的自我解釋,但是我會為每個部分解釋了。

首先,我們定義一些進口(即其他文件解析),我喜歡我的配置,例如組 DAO的在一個文件中,公用事業及其他適當的文件名稱。 雖然有點慢加快了維修的配置文件。 它也可以分析其它格式的文件使用不同的進口標誌。 文件被解析,以便與新的定義覆蓋或修改先前定義的服務 /參數。

接下來,我們定義了一個參數,一個參數一般都可以任何PHP變量的類型。 在這一點上我不知道我的用戶名參數應該是(我需要進行身份驗證這一點!),所以我定義了一個默認值,我將覆蓋該值後。 注意,類實例,直到你不問他們,待會兒定義參數是完全沒有。 在此之後我定義了一些服務:

  1. 實例Pro_Customer,通過一個實例,我記錄的setLogger()方法中,添加在我的MySQL的 數據訪問對象 (DAO)的,並通過在用戶名以及。 每次我問這個對象我希望有一個新的實例
  2. 創建一個實例 Pro_Product,傳遞參數的用戶名和一個選項數組構造。 在實例化之後調用 setDao(),並將它傳遞我的產品的DAO
  3. 給我一個副本Pro_Logger,實例化它使用getInstance()方法並傳遞一個作家我的檔案複製對象通過 setHandle()一旦其載入。 我的檔案作家的定義是我的一個進口。

在配置文件服務的名稱前加上引用以'@'符號,引用參數和附加與前面加上'%'符號,eg@utils.logger%的用戶名%。

加載數據後添加

有時候,你不知道的參數值後,才應該是你自舉,與我們的用戶參數以上。 為了覆蓋值offsetSet()方法時,首先傳遞參數名稱,後面的新值:

  $容器> offsetSet('用戶名',$用戶名); 

從容器中獲取對象

一旦安裝,而不是直接實例化對象,我們現在去的DI容器獲得實例。 隨著Symfony的 ​​直接投資,我們調用getService()方法,傳遞一個字符串,描述了變量,你想檢索,如

  = $ $記錄器容器> GetService的('utils.logger'); 

這將執行相當於:

  $記錄 = Pro_Logger::getInstance()方法;
新Pro_Writer_FileWriter $ fileWriter =();
 $記錄器-> setHandler($ fileWriter); 

這是可能的,以確定該容器有一個實例的服務調用hasService()方法,該方法返回一個布爾值。

它不需要有訪問容器之外的頂層應用程序的一個實例,因為一旦檢索所有所需的依賴關係,下至最深深度應用程序已經安裝並等待調用。

單元測試

依賴注入也有額外的好處讓被測試對象的孤立。 決策者類的例子實施前設置的依賴注入,我們的測試結果也依賴於實施DecisionParameters類。

如果DecisionParameters類返回不同的結果不就可以開始我們的測試,通過我們自己沒有過錯。 使用依賴注入,我們現在可以通過在DecisionParameters對象返回一個已知/固定的結果集為某些輸入參數,我們正在測試決策者孤立於任何外部因素,也就是說,如果我們的測試開始如果做不到這一點,可直接歸因於東西不斷變化的DecisionMakeer類。 這一點尤為重要,你應該是依靠測試數據從數據庫中進行測試。

應用程序配置

以何種方式表現你的應用程序在您的生產服務器將不可避免地不同於您的開發設置。 例如,在開發環境中的日誌記錄的水平會更精細比您的生產系統。 通過改變你的依賴注入容器的配置文件略(或分析一個額外的配置文件)的行為而改變對環境變得簡單。

通過提示的類型實現的接口上,而不是依賴它時設置你還可以換出兼容的組件與元件的幾行YAML的或XML。 例如,您可以訪問您的數據庫,目前通過一個MySQL的DAO(數據訪問對象),但假以時日,你可以開發一個PDO,Zend_Db的,或學說實現這種DAO。 通過添加新的實現到您的配置文件突然所有的對象,使用舊的MySQL實現正用你的新的實施攻擊,而無需應用程序的腸子。

註釋

  • 通過設置共享:真正的配置,我們總是給予同樣的實例的對象。 這是非常有用的對象打交道時,其中包含資源,如數據庫連接,文件句柄等
  • 有兩種方法依賴可以被注入。 其一是通過依賴與構造,或者通過 setter方法​​。 普遍接受的模式,就是把所需的依賴關係通過構造和自選項目通過 setter方法​​。 我個人偏好是使用二傳手的一切,但這是下到個人開發

終於 ...。

隨著一個簡短的討論依賴注入和它的優點和缺點這也是一個快速入門指南執行 symfony的依賴注入容器...希望你已經看到,它的驚人的快速和容易。 從這裡你就可以開始使用依賴注入你的應用程序,並期待通過使用更多的高級功能(雖然簡單的例子,涵蓋了絕大多數的功能,你會需要)。 一如往常我點你的手冊獲取更多信息。

4回應“快速啟動 Symfony的直接投資(依賴注入)教程”

  1. [...]這個職位提到的Twitter的文森特茹斯,史蒂芬勞埃德沃特。 史蒂芬勞埃德沃特金斯說: http://bit.ly/cUO2ov快速啟動symfony的 ​​依賴注入框架###採埃孚的PHP [...]

  2. 哈日觀塘 說:

    偉大的文章。
    現在我有一個疑問。 當引導我們裝載的YAML配置文件。 這是否對所有創建對象,這是我們不需要?
    對於例如:我有一個類的東西是用來只是有時。 因此,它創建了一個對象,還是足夠聰明,通過自動加載加載功能,當我調用 getInstance()方法。 我沒有拿到,即為什麼。

    謝謝

  3. 不,僅載入類時,首先需要。

    中的getInstance()在類實例化的例子,如:
    = $類類::getInstance()方法;
    而不是:
    $類 =新的類別();
    一般來說,這是執行時使用Singleton模式。

  4. [...]讓你用你的項目中直接投資在一個簡單的方法。 史蒂芬勞埃德沃特金斯花費的時間寫一個快速啟動 tutorial.It值得一提的是Symfony的DI容器是一個可以作為一個獨立的庫 Symfony的[...]

給一個答复













全景主題 Themocracy

現在 6訪客在線
6位遊客,0機器人,0位會員
最大遊客今日:13日上午12點 19分聯合技術
本月:26日2011年7月5日上午12點 35分聯合技術
今年:130 28-03-2011下午10時 40聯合技術
所有時間:130 28-03-2011下午10時 40聯合技術