如何从Symfony2 config.yml中读取配置设置?


191

我已经将设置添加到了config.yml文件中,如下所示:

app.config:
    contact_email: somebody@gmail.com
    ...

对于我的一生,我无法弄清楚如何将其读入变量。我在其中一个控制器中尝试过类似的操作:

$recipient =
$this->container->getParameter('contact_email');

但我收到一个错误消息:

必须定义参数“ contact_email”。

我已经清除了缓存,还查看了Symfony2重新加载的站点文档中的所有内容,但是我找不到执行该操作的方法。

现在可能太累了,无法解决这个问题。有人能帮忙吗?

Answers:


194

与其contact_emailapp.config中定义,而不是在parameters条目中定义:

parameters:
    contact_email: somebody@gmail.com

您应该找到正在控制器内进行的呼叫现在可以正常工作。


4
在Dev / Prod环境中如何使用?所以对于测试我想要的电子邮件发送给测试电子邮件和生产会得到另一个电子邮件
菲尔Pafford

2
@Phill:如果您在symfony2中使用标准的swiftmailer,则可以在config_dev.yml中使用以下设置: swiftmailer: delivery_address: dev@example.com 您可以在Symfony2食谱中
Pierre

4
$ this-> container-> getParameter('contact_email');使用此语句时,是否应该在所有地方注入容器类(控制器,实体,类)??还是有一种更简单的方法而无需注入容器类?
webblover

1
根据此解决方案,我如何访问嵌套属性?
奥斯曼

1
@webblover使用只需插入参数本身%parameter_name%的符号(在YAML) -
MauganRa

173

正如其他答案中所建议的那样,尽管将其移动contact_email到的解决方案parameters.yml很容易,但是如果您处理许多包或处理嵌套的配置块,则很容易使参数文件混乱。

  • 首先,我将严格回答这个问题。
  • 稍后,我将提供一种无需从公共空间传递任何参数就可以从服务获取这些配置的方法。

第一种方法:分离的配置块,将其作为参数

使用扩展名(此处有更多扩展名),您可以轻松地将其“分离”到中的不同块中config.yml,然后将其作为可从控制器获取的参数注入。

在扩展类的内部 DependencyInjection目录编写以下代码:

class MyNiceProjectExtension extends Extension
{
    public function load( array $configs, ContainerBuilder $container )
    {
        // The next 2 lines are pretty common to all Extension templates.
        $configuration = new Configuration();
        $processedConfig = $this->processConfiguration( $configuration, $configs );

        // This is the KEY TO YOUR ANSWER
        $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ] );

        // Other stuff like loading services.yml
    }

然后在您的config.yml中,config_dev.yml中,这样您就可以设置

my_nice_project:
    contact_email: someone@example.com

为了能够config.yml在您的内部进行处理,您MyNiceBundleExtension还需要一个Configuration在相同名称空间中使用类:

class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root( 'my_nice_project' );

        $rootNode->children()->scalarNode( 'contact_email' )->end();

        return $treeBuilder;
    }
}

然后,您可以按照原始问题的需要从控制器获取配置,但要保持parameters.yml清洁,并config.yml在单独的部分中进行设置:

$recipient = $this->container->getParameter( 'my_nice_project.contact_email' );

第二种方法:分离配置块,将配置注入服务

对于正在寻找类似东西但要从服务中获取配置的读者,甚至有一种更好的方法,它永远不会使“参数”公共空间混乱,甚至不需要将container其传递给服务(通过整个容器来实践)避免)。

上面的技巧仍然可以“注入”配置中的参数空间。

不过,在加载服务定义之后,您可以添加一个方法调用,例如setConfig(),该方法调用仅将阻塞插入到服务中。

例如,在扩展类中:

class MyNiceProjectExtension extends Extension
{
    public function load( array $configs, ContainerBuilder $container )
    {
        $configuration = new Configuration();
        $processedConfig = $this->processConfiguration( $configuration, $configs );

        // Do not add a paramater now, just continue reading the services.
        $loader = new YamlFileLoader( $container, new FileLocator( __DIR__ . '/../Resources/config' ) );
        $loader->load( 'services.yml' );

        // Once the services definition are read, get your service and add a method call to setConfig()
        $sillyServiceDefintion = $container->getDefinition( 'my.niceproject.sillymanager' );
        $sillyServiceDefintion->addMethodCall( 'setConfig', array( $processedConfig[ 'contact_email' ] ) );
    }
}

然后,您services.yml可以像往常一样定义服务,而无需进行任何绝对更改:

services:
    my.niceproject.sillymanager:
        class: My\NiceProjectBundle\Model\SillyManager
        arguments: []

然后在您的SillyManager类中,只需添加方法:

class SillyManager
{
    private $contact_email;

    public function setConfig( $newConfigContactEmail )
    {
        $this->contact_email = $newConfigContactEmail;
    }
}

注意,这也适用于数组而不是标量值!想象一下,您配置了一个兔子队列并需要主机,用户和密码:

my_nice_project:
    amqp:
        host: 192.168.33.55
        user: guest
        password: guest

当然,您需要更改树,但是您可以执行以下操作:

$sillyServiceDefintion->addMethodCall( 'setConfig', array( $processedConfig[ 'amqp' ] ) );

然后在服务中执行以下操作:

class SillyManager
{
    private $host;
    private $user;
    private $password;

    public function setConfig( $config )
    {
        $this->host = $config[ 'host' ];
        $this->user = $config[ 'user' ];
        $this->password = $config[ 'password' ];
    }
}

希望这可以帮助!


如果您想知道第一种方法和文档之间有什么不同,那就是MyNiceProjectExtension->load()使用以下行将config值转换为方法中的参数:$container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ]);。谢谢哈维!
jxmallett 2015年

完美的答案,可耻的symfony不允许您像配置参数一样访问配置。
马丁·林恩

这是一个很好的答案,但是它确实暴露了Symfony的“配置”应用程序的晦涩方式。当您必须编写和调用特定服务来访问它们时,拥有任意环境配置文件的意义何在?Symfony的人没有坐在那里意识到:“也许开发人员实际上想在他们的应用程序中提供他们可以访问的特定于环境的值”,这不是配置文件的意思吗?他们遵循“ STKTFANREO”设计模式:“将旋钮设置为F'd并将其撕掉”
eggmatters

它有多个应用程序,特别是在部署并行化自动测试时,以及在团队开发主要由模型或逻辑组成的捆绑软件时,该捆绑软件主要由其他团队在不同应用程序中使用,例如,作为用户前端的应用程序,另一个是管理面板的Web Front,另一个是REST API。这些都是不同的应用程序,它们愿意进行不同的配置。这乘以几种环境(生产,预生产,测试,开发等)。在单个公司中,这很容易获得12或15种配置。
哈维·蒙特罗

@XaviMontero我遵循了您的指令第二种方法:var_dump $ this-> contact_email或在函数setConfig()中添加exit()时,它不会退出。好像没有调用setConfig
user742736

35

我必须添加道格拉斯的答案,您可以访问全局配置,但是symfony会转换一些参数,例如:

# config.yml
... 
framework:
    session:
        domain: 'localhost'
...

$this->container->parameters['session.storage.options']['domain'];

您可以使用var_dump搜索指定的键或值。


17

为了能够为您的捆绑包提供一些配置参数,您应该查阅文档。这很容易做到:)

这是链接:如何公开捆绑软件的语义配置


老实说,这个问题是两年多以前问的,当时,上面的文章不存在。
josef.van.niekerk

10
我同意那句话。如果有人今天打开本文,我已经设置了答案。感谢您的负面评价-您过得很愉快。
Nikola Petkanski

我很抱歉,现在我想到了,我没有必要投票。感谢您的贡献,我尝试过投票,但是SO不允许了。该链接最有帮助,我相信其他人也会从中受益!也许管理员可以帮助改变我的看法???
josef.van.niekerk

我相信您可以再次单击以撤消。
Nikola Petkanski 2013年

在您完成表决后,或者在对消息进行编辑之前,您最多不能撤消X(5?)分钟的投票
Cheesemacfly 2013年


3

我从http://tutorial.symblog.co.uk/的代码示例中学到了一种简单的方法

1)注意ZendeskBlueFormBundle和文件位置

# myproject/app/config/config.yml

imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: @ZendeskBlueFormBundle/Resources/config/config.yml }

framework:

2)注意Zendesk_BlueForm.emails.contact_email和文件位置

# myproject/src/Zendesk/BlueFormBundle/Resources/config/config.yml

parameters:
    # Zendesk contact email address
    Zendesk_BlueForm.emails.contact_email: dunnleaddress@gmail.com

3)注意我如何在$ client和控制器的文件位置中获取它

# myproject/src/Zendesk/BlueFormBundle/Controller/PageController.php

    public function blueFormAction($name, $arg1, $arg2, $arg3, Request $request)
    {
    $client = new ZendeskAPI($this->container->getParameter("Zendesk_BlueForm.emails.contact_email"));
    ...
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.