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

时间:2015-02-25 07:30:40

标签: php symfony

我试图从数据库中加载它们,而不是在parameters.yml中对参数进行硬编码。并非所有parameters.yml中的参数都需要从数据库中加载,例如paypal的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);

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:13)

你做错了事。您需要声明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);
        }
    }
    
  • 在包定义类中,您需要将编译器传递添加到容器

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

答案 1 :(得分:1)

在我的情况下,使用CompilerPass的解决方案在Symfony 4中不起作用,它只能在控制器上起作用,而在twig.yaml文件中使用时无效:

param_name: '%param_name%'

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

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

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

class Settings
{
    /** @var \PDO */
    private $db;

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

    /**
     * Gets a setting value. 
     * If the setting doesn't exist, returns the default value specified as second param
     */
    public function get(string $name, $default=''): string
    {
            $stmt = $this->db->prepare("SELECT `value` FROM `settings` WHERE `key`=?;");
            $stmt->execute([$name]);
            return $stmt->fetchColumn() ?: $default;
    }

    /**
     * Sets a setting value. 
     * If the setting doesn't exists, it creates it. Otherwise, it replaces the db value
     */
    public function set(string $name, string $value, string $description = '')
    {
        $this->db->prepare("INSERT INTO settings (`key`, `value`, `description`) VALUES (?,?,?) ON DUPLICATE KEY UPDATE `value`=?;")
            ->execute([$name, $value, $description, $value]);
    }

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

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

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

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

我发布的Settings类得到了简化,例如,如果您多次请求相同的设置,避免再次进行相同的查询,仍然可以进行改进,但这很简单(将获取的密钥存储在{{1 }}数组)