首页 > 解决方案 > 如何在没有实际注入的情况下访问 Symfony 4 中的依赖注入容器?

问题描述

我有一个用 Symfony 4 编写的项目(如果需要,可以更新到最新版本)。在其中我有类似的情况:

有一个控制器向外部系统发送请求。它遍历数据库中的记录并为每一行发送一个请求。为此,有一个MagicApiConnector连接到外部系统的类,并且对于每个请求都有一个XxxRequest类(如FooRequestBarRequest等)。

所以,像这样的一般:

foreach ( $allRows as $row ) {
    $request = new FooRequest($row['a'], $row['b']);
    $connector->send($request);
}

现在为了完成所有的参数填充魔法,请求需要访问一个在 Symfony 的 DI 中定义的服务。控制器本身既不知道也不关心这个服务,但请求需要它。

我的请求类如何访问此服务?我不想将它设置为控制器的依赖项 - 我可以,但这似乎有点尴尬,因为控制器真的不关心它,只会通过它。这是请求的一个实现细节,我觉得它不应该给请求的用户带来这个样板要求的负担。

再说一次,有时您需要以更大的利益的名义做出牺牲,所以也许这就是其中一种情况?感觉自己是在“逆水行舟”,没有掌握一些思想观念。


补充:好的,完整的血腥细节,没有简化。

这一切都发生在两个自制系统的背景下。我们称它们为 OldApp 和 NewApp。两者都是 API,NewApp 正在调用 OldApp。API 是简单的 REST/JSON 风格。OldApp 不是基于 Symfony 构建的(大多数情况下甚至不使用框架),NewApp 是。我的问题是关于 NewApp。

OldApp API 的身份验证有三种不同的风格,如果需要,将来可能会得到更多(它还没有死!)不同的 API 调用使用不同的身份验证方法;有时甚至可以使用不同的方法使用相同的 API 调用(取决于调用它的人)。所有这些身份验证方法也是自制的。一个使用 POST 字段,另一个使用自定义 HTTP 标头,第三个不记得了。

现在,NewApp 被分发给许多用户的 Android 应用程序调用。Android 应用实际上同时使用了 NewApp 和 OldApp。当它调用 NewApp 时,它会传递额外的 HTTP 标头以及 OldApp 的身份验证数据(方法 1)。因此,NewApp 可以为 OldApp 冒充 Android 应用用户。此外,NewApp 还需要使用 OldApp 的一个用户自己无法调用的特殊命令(权限问题)。因此,它对该命令使用不同的身份验证机制(方法 2)。该命令的参数存储在本地配置(环境变量)中。

在我之前,一位同事创建了 a 的方案APIConnectorAPICommand您将连接器作为依赖项获取并根据需要创建命令实例。连接器实际执行 HTTP 请求;命令告诉它要发送哪些 POST 字段和哪些标头。我希望保留这个计划。

但是现在不同的身份验证机制如何适应这一点?每个命令都应该能够将它需要的东西传递给连接器;并且这些机制应该可用于多个命令。但是一个需要访问传入的请求,另一个需要访问配置参数。两者都不是通过 DI 实例化的。如何优雅地做到这一点?

标签: symfonydependency-injection

解决方案


这听起来像是工厂的工作。

function action(MyRequestFactory $requestFactory)
{
    foreach ( $allRows as $row ) {
        $request = $requestFactory->createFoo($row['a'], $row['b']);
        $connector->send($request);
    }

工厂本身作为服务并作为正常 Symfony 设计的一部分注入到控制器中。无论需要什么额外的服务都将被注入工厂。反过来,工厂可以在创建请求时提供各个请求可能碰巧需要的任何服务。


推荐阅读