我正在设置一个多租户Symfony 4应用程序,其中每个租户都有自己的数据库。
我在doctrine.yaml
配置中建立了两个数据库连接。连接之一是基于env变量的静态连接。另一个应该具有基于凭据提供程序服务的动态URL。
doctrine:
dbal:
connections:
default:
url: "@=service('provider.db.credentials').getUrl()"
上面的表达式"@=service('provider.db.credentials').getUrl()"
未被解析。
在将"@=service('provider.db.credentials').getUrl()"
作为参数注入另一个服务时,getUrl()
服务上的provider.db.credentials
的结果也被注入。但是,当在连接配置中将其用于主义时,表达式不会被解析。
有人知道如何解决吗?
答案 0 :(得分:1)
您试图依靠Symfony服务定义的ability来使用表达式定义服务的某些方面。但是,您需要记住,此功能是依赖注入组件的一部分,该组件能够(但不限于)将配置文件用于服务。更准确地说-配置加载程序提供了此功能,例如,您可以查看here来说明Yaml配置加载程序如何处理它。
另一方面,Doctrine捆绑包的配置由 Config 组件提供。 Dependency Injection组件使用与Config组件相同的文件格式的事实可能会给人一种印象,即这些情况是以相同的方式处理的,但实际上它们是完全不同的。
总而言之:Doctrine配置中的表达式无法按您期望的那样工作,因为Doctrine捆绑配置处理器不希望获得Expression Language表达式,并且不支持对其进行处理。
希望上面给出的解释能够回答您的问题-您可能希望获得一些有关如何实际解决问题的信息。
至少有两种方法可以执行此操作,但是选择正确的方法可能需要一些其他信息,这不在此问题的范围内。
在某种情况下,如果您知道在构建容器时选择哪个连接(您的代码假设是这种情况,但您可能不知道)-那么您应该使用compiler pass机制来更新Doctrine DBAL服务定义(这可能很棘手)。之所以如此重要,是因为配置是在容器构建过程的早期阶段加载的,并且没有提供扩展点。如有必要,您可以查看sources。无论如何,虽然可能,但我不建议您采用这种方式,并且很可能您将不需要它,因为(我想)您需要在运行时而不是在容器构建时选择连接。
可能更正确的方法是创建自己的DBAL Connection
类包装,该包装将维护实际连接列表并根据应用程序的逻辑提供所需的连接。您可以以DBAL sharding功能的实现细节为例。使用wrapper_class
配置的dbal
键,可以通过Doctrine捆绑包配置直接定义包装器类