【发布时间】:2017-10-07 14:26:53
【问题描述】:
我在我的 Symfony 2.8 API 项目中遇到了一个我自己无法解决的问题:
我在我的一个包的 DependencyInjection 中通过编译器加载了一些参数:
class ParametersCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
//loads api version from database when container gets built.
$api_version = $container->get('doctrine')->getRepository('MyAppEntityBundle:Parameter')
->findOneBy(['name' => 'api_version']);
if (!$api_version) {
throw new MyAppException('api_version couldnt be found in database during container build process.');
}
$container->setParameter('api_version', $api_version);
}
}
我不想在 paramters_*.yml 文件中使用这个参数,以确保它总是从 db 中检索到 + 我在 security.yml 文件中使用它,例如:
security:
firewalls:
api:
pattern: ^/api/%api_version%/
我怎样才能做到这一点?
显然,$container->setParameter('name', $value);如果 parameter_*.yml 文件中没有参数且parameters.yml 中有虚拟值,则不起作用 + 我需要在 security.yml 被解析和加载之前设置这些值。 我研究了 symfony 核心几个小时,发现了从 kernel->boot() 进程加载安全配置的位置,但我不知道如何正确实现我想要的。
任何有关正确方法的帮助或提示将不胜感激:)
【问题讨论】:
-
所有配置文件解析都在调用任何通道之前完成。所以是的,你总是需要一个虚拟值。与 setParameter 无关。您可以查看 SecurityBundle 传递如何使其成为服务,并可能更改传递中的定义。但是从 pass 内部访问数据库是不寻常的。我怀疑它是否会起作用。
-
防火墙的目标是什么?如前所述,使用编译器通道将在编译时充当 db 值的缓存
app/console cache:warmup,并且不会在 db 值发生变化时更改,除非您重新编译您的应用程序。这在生产中会令人困惑和不受欢迎。使用security provider 在访问时而不是在编译时验证用户更有意义。然后,您可以执行自己的查询来验证每个请求的api_version。 -
@Cerad,我从我的源代码中删除了这个,但我很确定它是,也许是因为运气好,学说是在我的包通过之前在容器中构建的?还是每个供应商的捆绑包都是在我之前构建的?抱歉,这些都是假设。好的,我知道如何更改安全服务定义,但对于我想要实现的目标来说,它过于复杂,无论如何感谢您的提示!
-
@fyrye 这不是关于制作防火墙(= 检查授权,就像你说的安全提供商,我有适当的 JWT 系统),我正在寻找一种通过设置自动化 API 部署的方法从管理应用程序中,将新版本的 api 部署到数据库中(简而言之,它比这更复杂,+ 移动应用程序更新需要)然后部署它。感谢您的提示,但我认为检查每个请求的 api_version 对性能不利:)
-
@yfhrpcx 防火墙的目的是确定“何时发生身份验证”。我认为这将取决于您想要的结果。因为所有
^/api请求都应该进行身份验证。然后,版本的路由将由 API 控制器/api/{version}处理。当api_version更改时,您当前的方法将禁用身份验证。例如当api_version: 'v2'是您想要的结果时,请求/api/v1?
标签: php symfony parameters compiler-construction containers