如何使用 Symfony2 访问控制器之外的服务? [英] How can I access a service outside of a controller with Symfony2?

查看:50
本文介绍了如何使用 Symfony2 访问控制器之外的服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个非常依赖第三方 API 的站点,因此我认为将 API 包装器打包为服务是有意义的,但是我开始寻找可以使用的实例在控制器之外访问它,例如在实体存储库中.与此相关的是,能够访问控制器外部的配置值(再次例如在实体存储库中)会很有用.

I'm building a site that relies quite heavily on a third party API so I thought it would make sense to package up the API wrapper as a service, however I'm starting to find instances where it would be useful to have access to it outside of a controller such as in an entity repository. Also related to that is it would be useful to be able to get access to config values outside of a controller (again such as in an entity repository).

谁能告诉我这是否可行,如果不可行,是否有建议的方法来做这种事情?

Can anyone tell me if this is possible and if not is there a suggested approach to doing this kind of thing?

感谢您的帮助

推荐答案

Symfony 发行版严重依赖依赖注入.这意味着通常,依赖项通过构造函数、setter 或其他方式(如对属性的反射)直接注入到您的对象中.然后,您的 API 包装器服务成为您应用程序其他对象的依赖项.

The Symfony distribution relies heavily on dependency injection. This means that usually, dependencies are injected directly into your object via the constructor, the setters or via other means (like reflection over properties). Your API wrapper service is then a dependency for other objects of your application.

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

That being said, it would be rather difficult to inject this service in an entity repository's constructor because it already requires some other parameters and I think it would not be possible to inject them because of the way we request the repository for an entity.

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

What you could do is to create another service which will be responsible of doing the work you were about to do in the entity repository. This way, you will be able to inject the entity manager, which will be used to retrieve the entity repository, you custom service and also another service holding your configuration values (There are other ways to share configuration values).

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

In my use case, I use a Facebook helper service that wraps Facebook API calls. This service is then injected where I need it. My entity repository is only responsible of doing database calls so it receives only the arguments it needs and not the whole dependency. Thus, it will not receive the helper but rather only the arguments needed to do a request, for example, a Facebook user id. In my opinion, this is the way to do it since I think the entity repository should not have dependencies on such helper objects.

这是一个使用 YAML 作为配置的小例子:

Here a small example using YAML as the configuration:

# 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,而不是简单的字符串.对于配置值,正如我之前所说,还有其他方法可以实现相同的目标,例如使用参数或捆绑扩展.使用捆绑扩展,您可以将配置值直接定义到 config.yml 中,您的捆绑将读取它们.

The at sign (@) in the config.yml file means that Symfony should inject another service ,having the id defined after the at sign, and not a simple string. For the configuration values, as I said previously, there is other means to achieve the same goal like using parameters or a bundle extension. With a bundle extension, you could define the configuration values directly into the config.yml and your bundle would read them.

总而言之,这应该能让您大致了解注入服务.这是有关该主题的一小部分文档列表.许多链接使用 XML 服务定义而不是 YAML 定义,但您应该能够很容易地理解它们.

In conclusion, this should give you the general idea of injecting services. Here a small list of documentation on the subject. Alot of links use the XML service definition instead of the YAML definition but you should be able to understand them quite easily.

  1. Symfony 官方 DI
  2. Fabien Potencier 关于 DI 的文章
  3. 理查德米勒关于 DI 的文章(在他的博客中查看其他 DI 文章)
  1. Symfony Official DI
  2. Fabien Potencier's articles on DI
  3. Richard Miller's articles on DI (Check in his blog for the other DI articles)

请注意,我提供的配置适用于 Symfony2 的 Beta1.我还没有更新到 Beta2,所以可能有些东西在 Beta2 版本中无法正常工作.

Take note that the configuration I'm giving is working for Beta1 of Symfony2. I didn't update yet to Beta2 so there could be some stuff not working as they are in the Beta2 version.

我希望这能帮助您确定问题的最终解决方案.如果您需要澄清或其他任何问题,请随时提出其他问题.

I hope this will help you defining a final solution to your problem. Don't hesitate to ask other questions if you want clarifications or anything else.

问候,马特

这篇关于如何使用 Symfony2 访问控制器之外的服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆