如何从数据库加载 Symfony 的配置参数 (Doctrine)

How to load Symfony's config parameters from database (Doctrine)

我尝试从数据库中加载参数,而不是对 parameters.yml 中的参数进行硬编码。并非 parameters.yml 中的所有参数都需要从数据库中加载,例如 api paypal 的详细信息

config.yml 我导入了 parameters.php

imports:
    - { resource: parameters.php }

如果我像下面那样在 parameters.php 中添加静态信息,它就可以正常工作

$demoName = 'First Last';
$container->setParameter('demoName', $demoName);

但是我无法从数据库 table 中获取信息。我以为我应该创建 class 并使用 $em = this->getDoctrine()->getManager(); 它应该可以工作但是没有,我得到

的错误

Notice: Undefined variable: paypal_data in /opt/lampp/htdocs/services/app/config/parameters.php (which is being imported from "/opt/lampp/htdocs/services/app/config/config.yml").

这是我所做的尝试,如下所示,但代码似乎没有进入 __construct()

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\ORM\Mapping as ORM;

class parameters extends Controller
{
    public $paypal_data;

    function __construct() {
        $this->indexAction();
    }

    public function indexAction(){

        $em = $this->getDoctrine()->getManager();
        $this->paypal_data = $em->getRepository('featureBundle:paymentGateways')->findAll();

    }

}
$demoName = 'First Last';
$container->setParameter('demoName', $demoName);
$container->setParameter('paypal_data', $this->paypal_data);

任何帮助将不胜感激。

你做错事了。您需要声明您的 CompilerPass 并将其添加到容器中。加载整个容器后...在编译时,您将可以访问其中的所有服务。

只需获取实体管理器服务并查询所需的参数并将它们注册到容器中即可。

分步说明:

  • 定义编译器传递:

    # src/Acme/YourBundle/DependencyInjection/Compiler/ParametersCompilerPass.php
    class ParametersCompilerPass implements CompilerPassInterface
    {
        public function process(ContainerBuilder $container)
        {
            $em = $container->get('doctrine.orm.default_entity_manager');
            $paypal_params = $em->getRepository('featureBundle:paymentGateways')->findAll();
            $container->setParameter('paypal_data', $paypal_params);
        }
    }
    
  • 在 bundle 定义中 class 您需要将编译器传递添加到您的容器中

    # src/Acme/YourBundle/AcmeYourBundle.php
    class AcmeYourBundle extends Bundle
    {
        public function build(ContainerBuilder $container)
        {
            parent::build($container);
    
            $container->addCompilerPass(new ParametersCompilerPass(), PassConfig::TYPE_AFTER_REMOVING);
        }
    }
    

CompilerPass 的解决方案在我的 Symfony 4 中不起作用,它只在控制器上起作用,但在 twig.yaml 文件中使用时不起作用:

param_name: '%param_name%'

由于我需要在侧边栏中使用这个参数,所以在所有页面中,从控制器传递它是不可行的。

这就是我所做的,感谢您可以 reference services 作为全局 Twig 变量。

我有一个名为“设置”的服务,它直接从数据库加载设置,简化了:

class Settings
{
    private Connection $db;

    public function __construct(EntityManagerInterface $em)
    {
        $this->db = $this->em->getConnection();
    }

    /**
     * Get a setting value. 
     * If the setting doesn't exist, return the default value specified as the second param
     */
    public function get(string $name, $default=''): string
    {
        $val = $this->db->executeQuery("SELECT `value` FROM `settings` WHERE `key`=?;", [$name])->fetchOne();
        // strict comparison is needed for cases when $val === '0'
        return $val !== false ? $val : $default;
    }

    /**
     * Set a setting value. 
     * If the setting doesn't exist, create it. Otherwise, replace the db value
     */
    public function set(string $name, ?string $value, string $description = '')
    {
        if(is_null($value)) {
            // Remove the key
            $this->db->executeQuery('DELETE FROM settings WHERE `key`=?;', [$name]);
            return;
        }

        $this->db->executeQuery('INSERT INTO settings (`key`, `type`, `value`, `description`) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE `type`=?, `value`=?, `description`=?;',
            [$name, $type, $value, $description, $type, $value, $description]);
    }

现在,我只是在 config/packages/twig.yaml 中添加:

twig:
    # ...
    globals:
        # ...
        settings: '@App\Service\Settings'

这太棒了,因为现在我可以从任何模板读取任何数据库设置:

{{ dump(settings.get('setting_name')) }}

我发布的设置 class 已简化,它仍然可以改进,例如,如果您多次请求相同的设置,可以避免再次进行相同的查询,但这很容易做到(存储获取的private $fetched 数组中的键)或 warmup(array $keys) 方法通过单个查询获取许多设置 ("SELECT key, value FROM settings WHERE key IN (?);", [$toFetch], [Connection::PARAM_STR_ARRAY])