我有一个用Symfony 4编写的项目(如果需要,可以更新到最新版本)。在这种情况下,我的情况与此类似:
有一个控制器可以将请求发送到外部系统。它遍历数据库中的记录,并为每一行发送一个请求。为此,有一个MagicApiConnector
类连接到外部系统,并且对于每个请求都有一个XxxRequest
类(例如FooRequest
,BarRequest
等)。 / p>
所以,类似这样的东西:
foreach ( $allRows as $row ) {
$request = new FooRequest($row['a'], $row['b']);
$connector->send($request);
}
现在,为了完成所有参数填充操作,请求需要访问Symfony的DI中定义的服务。控制器本身既不知道也不关心此服务,但是请求需要它。
我的请求类别如何访问此服务?我不想将其设置为控制器的依赖项-我可以,但是似乎有点尴尬,因为控制器实际上并不关心它,只会通过它。这是请求的实现细节,我觉得它不应该让样板需求负担请求的用户。
那么,有时您需要以更大的利益为名做出牺牲,那么也许是其中一种情况?感觉就像我在“背叛”,没有掌握一些思想观念。
已添加:确定,详细的gory详细信息,无任何简化。
这一切都是在两个自制系统的情况下发生的。我们称它们为OldApp和NewApp。两者都是API,NewApp正在调用OldApp。这些API是简单的REST / JSON样式。 OldApp不是基于Symfony构建的(大多数甚至不使用框架),NewApp是。我的问题是关于NewApp。
OldApp API的身份验证采用三种不同的方式,并且在将来需要时可能会得到更多的应用(这还没有结束!)。不同的API调用使用不同的身份验证方法。有时即使是同一API调用也可以使用不同的方法(取决于调用它的人)。所有这些认证方法也是自制的。一个使用POST字段,另一个使用自定义HTTP标头,不记得第三个。
现在,已分发给许多用户的Android应用正在调用NewApp。 Android应用程序实际上同时使用NewApp和OldApp。当它调用NewApp时,它将传递带有OldApp身份验证数据的额外HTTP标头(方法1)。因此,NewApp可以模拟OldApp的Android应用程序用户。此外,NewApp还需要使用用户自己无法调用的OldApp特殊命令(特权问题)。因此,它对该命令使用了不同的身份验证机制(方法2)。该命令的参数存储在本地配置中(环境变量)。
在我之前,一位同事创建了APIConnector
和APICommand
的方案,在其中您将连接器作为依赖项并根据需要创建命令实例。连接器实际上执行HTTP请求;这些命令告诉它哪些POST字段和要发送的标头。我希望保留这个方案。
但是现在不同的身份验证机制又如何适应呢?每个命令都应该能够将所需的内容传递给连接器。并且该机制应可用于多个命令。但是一个需要访问传入的请求,另一个需要访问配置参数。两者都不通过DI实例化。如何优雅地做到这一点?
答案 0 :(得分:3)
这听起来像是工厂的工作。
function action(MyRequestFactory $requestFactory)
{
foreach ( $allRows as $row ) {
$request = $requestFactory->createFoo($row['a'], $row['b']);
$connector->send($request);
}
工厂本身是一种服务,并作为正常Symfony设计的一部分注入到控制器中。无论需要任何其他服务,都将注入工厂。反过来,工厂可以在创建请求时提供单个请求可能需要的任何服务。