【发布时间】:2011-09-01 17:44:32
【问题描述】:
我正在构建一个非常依赖第三方 API 的网站,因此我认为将 API 包装器打包为服务是有意义的,但是我开始寻找使用它的实例在控制器之外访问它,例如在实体存储库中。 与此相关的还有,能够访问控制器之外的配置值(例如在实体存储库中)将很有用。
谁能告诉我这是否可行,如果不可行,是否有建议的方法来做这种事情?
感谢您的帮助
【问题讨论】:
我正在构建一个非常依赖第三方 API 的网站,因此我认为将 API 包装器打包为服务是有意义的,但是我开始寻找使用它的实例在控制器之外访问它,例如在实体存储库中。 与此相关的还有,能够访问控制器之外的配置值(例如在实体存储库中)将很有用。
谁能告诉我这是否可行,如果不可行,是否有建议的方法来做这种事情?
感谢您的帮助
【问题讨论】:
Symfony 发行版严重依赖依赖注入。这意味着通常,依赖项通过构造函数、设置器或其他方式(如属性反射)直接注入到您的对象中。然后,您的 API 包装服务成为您应用程序其他对象的依赖项。
话虽如此,在实体存储库的构造函数中注入此服务是相当困难的,因为它已经需要一些其他参数,而且我认为由于我们为实体请求存储库的方式而无法注入它们.
您可以做的是创建另一个服务,该服务将负责执行您将在实体存储库中执行的工作。这样,您将能够注入实体管理器,该管理器将用于检索实体存储库、您的自定义服务以及另一个保存您的配置值的服务(还有其他方法可以共享配置值)。
在我的用例中,我使用了一个包装 Facebook API 调用的 Facebook 帮助服务。然后将此服务注入我需要的地方。我的实体存储库只负责进行数据库调用,因此它只接收它需要的参数而不是整个依赖项。因此,它不会接收帮助程序,而只会接收执行请求所需的参数,例如 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 应该注入另一个服务,其 id 定义在 at 符号之后,而不是简单的字符串。对于配置值,正如我之前所说,还有其他方法可以实现相同的目标,例如使用参数或捆绑扩展。使用 bundle 扩展,您可以将配置值直接定义到 config.yml 中,并且您的 bundle 会读取它们。
总之,这应该让您大致了解注入服务。这里是有关该主题的文档的小列表。许多链接使用 XML 服务定义而不是 YAML 定义,但您应该能够很容易地理解它们。
请注意,我提供的配置适用于 Symfony2 的 Beta1。我还没有更新到 Beta2,所以可能有一些东西在 Beta2 版本中无法正常工作。
我希望这将帮助您确定问题的最终解决方案。如果您需要澄清或其他任何问题,请随时提出其他问题。
问候, 马特
【讨论】:
__constructor 而不是__construct,顺便说一下答案+1!
我会将这种行为封装在 Symfony 服务中(如管理器)。 我不会将任何参数或逻辑注入实体存储库,因为它们应该主要用于使用对象管理器查询获取数据。 我会将逻辑放在服务中,如果服务需要访问数据库,它将调用实体存储库来获取数据。
【讨论】: