【问题标题】:Load Symfony (5.2) config from database从数据库加载 Symfony (5.2) 配置
【发布时间】:2021-02-26 09:09:55
【问题描述】:

我是 Symfony 的新手,但我知道如何在 PHP 中使用 OOP。 我尝试(沮丧地)使用 Doctrine 实体将自定义参数与 Symfony 配置结合起来。

为了解决我使用的问题,例如Michael Sivolobov 的回答:https://stackoverflow.com/a/28726681/2114615 和其他来源。

我的解决方案:

第 1 步:在 config 文件夹中创建新包

-> config
  -> packages
   -> project
   -> services.yaml
   -> project
    -> src
    -> ParameterLoaderBundle.php
    -> DependencyInjection
     -> Compiler
     -> ParameterLoaderPass.php

第 2 步:导入新资源

# config/services.yaml
...
imports:
    - { resource: 'packages/project/config/services.yaml' }
...

第 3 步:包装编码

# packages/project/config/services.yaml

services:
    Project\:
        resource: "../src"
<?php

namespace Project;

use Project\DependencyInjection\Compiler\ParameterLoaderPass;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class ParameterLoaderBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);

        $container->addCompilerPass(new ParameterLoaderPass(), PassConfig::TYPE_AFTER_REMOVING);
    }
}
<?php

namespace Project\DependencyInjection\Compiler;

use App\Entity\SettingCategory;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ParameterLoaderPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $em = $container->get('doctrine.orm.default_entity_manager');
        $setting = $em->getRepository(SettingCategory::class)->findAll();
        $container->setParameter('test', $setting);
    }
}

毕竟我在我的 API 控制器中测试了新参数:

$this->getParameter('Test');

但出现以下错误信息:

The parameter \"test\" must be defined.

【问题讨论】:

  • 您班级的路径不符合 PSR4 标准。看起来目录名称是compiler,但应该是Compiler
  • 文件夹“compiler”的正确名称是“Compiler”。抱歉打错了。
  • 发布类所在文件的确切路径名。无法理解您上面的图表。看起来该文件不在Compiler 内。
  • 我不知道为什么,但是错误消失了。另一方面,我的解决方案不起作用,我没有得到参数: $container->setParameter('test', $setting);

标签: symfony doctrine config


【解决方案1】:

这里发生了几件事。首先,从数据库加载配置在 Symfony 中是非常不寻常的,所以遇到困难也就不足为奇了。其次,您的流程代码永远不会被调用。调试的一部分是确保您期望被调用的代码实际上正在被调用。第三,您确实在尝试在 config.js 下添加捆绑包时遇到了问题。早在 Symfony 2 中,app/config 下曾经有更多与 bundle 相关的东西,可能是您发现了一些旧文章并误解了它们。

但是,这里最大的问题是 Symfony 有一个所谓的“编译”阶段,它基本上处理所有配置并缓存它。因此 CompilerPassInterface。不幸的是,服务本身在编译阶段不可用。他们根本不存在,所以没有实体经理。如果您真的想从数据库加载配置,您需要打开自己的数据库连接。您将只想使用数据库连接对象而不是实体管理器,因为编译阶段的一部分是处理实体本身。

所以摆脱你所有的代码,只需调整你的内核类:

# src/Kernel.php
class Kernel extends BaseKernel implements CompilerPassInterface
{
    use MicroKernelTrait;

    public function process(ContainerBuilder $container)
    {
        $url = $_ENV['DATABASE_URL'];
        $conn = DriverManager::getConnection(['url' => $url]);

        $settings = $conn->executeQuery('SELECT * FROM settings')->fetchAllAssociative();
        $container->setParameter('test',$settings);
    }

请注意,即使您完成了所有这些工作,您也需要在更新设置表后手动重建 Symfony 缓存。它不会是自动的。你真的可以考虑采取完全不同的方法。

【讨论】:

  • 您好 Cerad,首先,感谢您的帮助和有用的信息。该解决方案对我有用,但您的意思是不建议使用它?在这种情况下,我找到了一个开源 Symfony 包 link。它将自定义参数保存在数据库表中,并通过服务提供。您对我的解决方案有什么建议(高效且对开发人员友好)?
  • 要理解的是所有参数最终都缓存在var/cache下。因此,更改设置表中的信息将需要重建缓存。数据不会在每个请求上重新加载。只要你能忍受它就可以了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-22
  • 1970-01-01
  • 1970-01-01
  • 2016-06-29
  • 2016-07-27
  • 2015-12-07
相关资源
最近更新 更多