如何使用Symfony2访问控制器外部的服务?

时间:2011-05-25 12:29:07

标签: symfony service

我正在构建一个非常依赖第三方API的网站,所以我认为将API包装器打包为服务是有意义的,但是我开始找到有用的实例。在控制器之外访问它,例如在实体存储库中。 与此相关的是能够访问控制器之外的配置值(例如在实体存储库中)也是有用的。

任何人都可以告诉我这是否可行,如果没有,是否有建议的方法来做这种事情?

感谢您的帮助

2 个答案:

答案 0 :(得分:74)

Symfony发行版在很大程度上依赖于依赖注入。这意味着通常,依赖项通过构造函数,setter或其他方式(如属性反射)直接注入到对象中。然后,您的API包装器服务是应用程序的其他对象的依赖项。

话虽如此,在实体存储库的构造函数中注入此服务会相当困难,因为它已经需要一些其他参数,我认为由于我们为实体请求存储库的方式而无法注入它们

您可以做的是创建另一项服务,该服务将负责您在实体存储库中执行的工作。这样,您就可以注入实体管理器,它将用于检索实体存储库,自定义服务以及另一个包含配置值的服务(还有其他方法可以共享配置值)。

在我的用例中,我使用Facebook帮助程序服务来包装Facebook API调用。然后将此服务注入我需要的地方。我的实体存储库只负责执行数据库调用,因此它只接收所需的参数而不是整个依赖项。因此,它不会接收帮助程序,而只接收执行请求所需的参数,例如,Facebook用户ID。在我看来,这是实现它的方法,因为我认为实体存储库不应该依赖于这样的辅助对象。

这是一个使用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文件中的at符号(@)表示Symfony应该注入另一个服务,在at符号后面定义了id,而不是简单的字符串。对于配置值,正如我之前所说,还有其他方法可以实现相同的目标,例如使用参数或bundle扩展。使用bundle扩展,你可以直接在config.yml中定义配置值,你的bundle会读取它们。

总之,这应该为您提供注入服务的一般概念。这里有一小部分关于这个主题的文档。很多链接使用XML服务定义而不是YAML定义,但您应该能够很容易地理解它们。

  1. Symfony Official DI
  2. Fabien Potencier's articles on DI
  3. Richard Miller's articles on DI(在他的博客中查看其他DI文章)
  4. 请注意,我给出的配置适用于Symfony2的Beta1。我还没有更新到Beta2,所以可能有些东西不能用于Beta2版本。

    我希望这可以帮助您定义问题的最终解决方案。如果您需要澄清或其他任何内容,请随时提出其他问题。

    此致 马特

答案 1 :(得分:0)

我会将这种行为包装在Symfony服务中(比如管理器)。 我不会将任何参数或逻辑注入实体存储库,因为它们应主要用于使用对象管理器查询获取数据。 我会将逻辑放在服务中,如果服务需要数据库访问,它将调用实体存储库来获取数据。