如何加载Symfony';数据库中的配置参数(条令)


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

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

config.yml中,我导入了parameters.php

imports:
    - { resource: parameters.php }

如果我像下面这样在parameters.php中添加静态信息,它可以很好地进行

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

但是,我无法从数据库表中获取信息。我想我应该创建类并使用$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定义类中,您需要将编译器传递添加到容器中

    # 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);
        }
    }
    

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

param_name: '%param_name%'

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

这就是我所做的,因为你可以将服务引用为全局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')) }}

我发布的Settings类被简化了,它仍然可以改进,例如,如果您多次请求相同的设置,则可以避免再次进行相同的查询,但这很简单(将提取的密钥存储在private $fetched数组中),或者使用warmup(array $keys)方法通过单个查询("SELECT key, value FROM settings WHERE key IN (?);", [$toFetch], [Connection::PARAM_STR_ARRAY])提取多个设置