2011-05-25 57 views
50

我正在建立一個網站,很大程度上依賴於第三方API,所以我認爲將API封裝器打包爲服務是有意義的,但是我已經開始發現有權訪問的實例它在控制器之外,比如在實體存儲庫中。 與此相關的是能夠訪問控制器之外的配置值(例如在實體存儲庫中)將是有用的。如何使用Symfony2訪問控制器之外的服務?

任何人都可以告訴我,如果這是可能的,如果不是有建議的方法做這種事情?

感謝您的任何幫助

回答

73

Symfony分佈嚴重依賴於依賴注入。這意味着通常,依賴關係通過構造函數,設置器或通過其他方式(如對屬性的反射)直接注入到對象中。您的API包裝服務是您的應用程序的其他對象的依賴項。這就是說,將這個服務注入到一個實體庫的構造函數中是相當困難的,因爲它已經需要一些其他參數了,​​我認爲它不可能被注入,因爲我們要求一個存儲庫的方式實體。

你可以做的是創建另一個服務,負責完成你將要在實體存儲庫中完成的工作。這樣,您將能夠注入將用於檢索實體存儲庫的實體管理器,自定義服務以及保存配置值的其他服務(還有其他方式可以共享配置值)。

在我的使用案例中,我使用了包裝Facebook API調用的Facebook幫助器服務。這個服務然後被注入我需要的地方。我的實體倉庫只負責進行數據庫調用,因此它只接收它需要的參數,而不是整個依賴項。因此,它不會收到助手,而只會收到請求所需的參數,例如Facebook用戶標識。在我看來,這是做這件事的方式,因爲我認爲實體存儲庫不應該對這樣的輔助對象有依賴關係。

這裏使用YAML作爲配置一個小例子:

# app/config/config.yml 
services: 
    yourapp.configuration_container: 
    class: Application/AcmeBundle/Common/ConfigurationContainer 
    # You could inject configurations here  

    yourapp.api_wrapper: 
    class: Application/AcmeBundle/Service/ApiWrapperService 
    # Inject other arguments if needed and update constructor in consequence  

    yourapp.data_access: 
    class: Application/AcmeBundle/Data/Access/DatabaseAccessService 
    arguments: 
     entityManager: "@doctrine.orm.entity_manager" 
     apiWrapperService: "@yourapp.api_wrapper" 
     configuration: "@yourapp.configuration_container" 

# Application/AcmeBundle/Common/ConfigurationContainer.php 
public ConfigurationContainer 
{ 
    public function __construct() 
    { 
     // Initialize your configuration values or inject them in the constructor 
    } 
}   

# Application/AcmeBundle/Service/ApiWrapperService.php 
public ApiWrapperService 
{ 
    public function __construct() 
    { 
     // Do some stuff 
    } 
} 

# Application/AcmeBundle/Data/Access/DatabaseAccessService.php 
public DatabaseAccessService 
{ 
    public function __construct(EntityManager $entityManager, ApiWrapperService $apiWrapperService, ConfigurationContainer $configuration) 
    { 
     ... 
    } 
} 

的符號(@)在config.yml文件指的Symfony應該注入另一服務中,具有後at符號所定義的ID,而不是一個簡單的字符串。正如我之前所說的,對於配置值來說,還有其他方法可以實現像使用參數或bundle擴展一樣的目標。使用包擴展,您可以將配置值直接定義到config.yml中,並且您的包將會讀取它們。

總之,這應該給你注射服務的總體思路。這裏有一個關於這個主題的文檔的小列表。許多鏈接使用XML服務定義而不是YAML定義,但您應該能夠很容易地理解它們。

  1. Symfony Official DI
  2. Fabien Potencier's articles on DI
  3. Richard Miller's articles on DI(請在自己的博客爲其他DI篇)

注意到,我給的配置工作的Symfony2的Beta1的。我沒有更新到Beta2,所以可能有些東西因爲它們在Beta2版本中不起作用。

我希望這可以幫助您爲問題定義最終解決方案。如果您想要澄清或其他任何問題,請不要猶豫提出其他問題。

問候, 馬特

+0

這是巨大的幫助,我已經將我的API服務注入到了我的數據庫服務中,這非常好,我仍然不清楚如何最好地繼續配置。如果我解釋我想要做什麼,可能是最好的。我正在構建一個可跨多個域使用的站點,每個站點都將作爲具有自己的yaml配置文件的環境存在。在配置文件中將是一個站點ID,我想要的是能夠調用getUsers()例如,並從配置中獲取站點ID,並自動向查詢中添加「where site_id = x」。這是可能的,或者我應該通過ID作爲參數? – pogo 2011-05-25 17:57:32

+1

剛剛意識到您鏈接的Symfony文章解釋瞭如何做到這一點,再次感謝您的幫助。這一直強調了我幾天,所以有一個解決方案是很好的。 – pogo 2011-05-25 18:02:19

+0

很高興它有幫助,你現在有一個解決你的問題:)的確,我鏈接的文章更加明確如何使用參數和類似的東西。祝你工作順利。 – Matt 2011-05-25 20:08:49

0

我想包這種行爲的Symfony的服務(如經理)。 我不會在實體存儲庫中注入任何參數或邏輯,因爲它們應該主要用於使用對象管理器查詢來獲取數據。 我會把邏輯放在服務中,如果服務需要數據庫訪問,它會調用實體存儲庫來獲取數據。

相關問題