【问题标题】:How do I read configuration settings from Symfony2 config.yml?如何从 Symfony2 config.yml 读取配置设置?
【发布时间】:2011-06-16 20:10:37
【问题描述】:

我已经在我的 config.yml 文件中添加了这样的设置:

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

对于我的生活,我无法弄清楚如何将它读入变量。我在我的一个控制器中尝试过这样的事情:

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

但我收到一条错误消息:

参数“contact_email”必须是 已定义。

我已经清除了我的缓存,我还到处查看 Symfony2 重新加载的站点文档,但我不知道如何做到这一点。

现在可能只是太累了,无法弄清楚。有人可以帮忙吗?

【问题讨论】:

    标签: symfony configuration


    【解决方案1】:

    不要在app.config 中定义contact_email,而是在parameters 条目中定义它:

    parameters:
        contact_email: somebody@gmail.com
    

    您应该会发现您在控制器中进行的调用现在可以正常工作了。

    【讨论】:

    • 这将如何与 Dev / Prod 环境一起工作?因此,对于测试,我希望将电子邮件发送到测试电子邮件,而生产会收到另一封电子邮件
    • @Phill:如果您在 symfony2 中使用标准 swiftmailer,您可以在 config_dev.yml 中使用以下设置:swiftmailer: delivery_address: dev@example.com 您可以在Symfony2 cookbook 中找到更多信息
    • 当我使用此语句 $this->container->getParameter('contact_email'); 时,我是否应该在所有地方注入容器类(控制器、实体、类)??或者有没有更简单的方法可以在不注入容器类的情况下做到这一点?
    • 根据这个解决方案如何访问嵌套属性?
    • @webblover 只需使用 %parameter_name% 插入参数本身 - 表示法(在 YAML 中)
    【解决方案2】:

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

    • 首先,我会严格回答这个问题。
    • 稍后,我将提供一种从服务中获取这些配置的方法,而无需通过公共空间作为参数传递。

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

    通过扩展 (more on extensions here),您可以轻松地将其“分离”到 config.yml 中的不同块中,然后将其作为可从控制器获取的参数注入。

    DependencyInjection 目录内的 Extension 类中写下:

    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
    

    为了能够在 MyNiceBundleExtension 中处理 config.yml,您还需要在同一命名空间中的 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(),它只将该块注入服务。

    例如在Extension类中:

    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() 方法中使用以下行转换为参数:$container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ]);。谢谢哈维!
    • 完美答案,耻辱 symfony 不允许您像访问参数一样访问配置。
    • 这是一个很好的答案,但它确实暴露了 Symfony 的“配置”应用程序的笨拙方式。当您必须编写和调用特定服务来访问它们时,拥有任意环境配置文件有什么意义。 Symfony 的某个人不是坐在那里意识到,“也许开发人员实际上希望在他们可以访问的应用程序中提供特定于环境的值” 配置文件的意义不是吗?他们遵循“STKTFANREO”设计模式:“将旋钮设置为 F'd 并撕掉它们”
    • 它有几个应用程序,特别是在部署并行自动测试时,特别是当一个团队开发一个主要是模型或逻辑的包时,该包被其他几个团队在不同的应用程序中使用,例如一个应用程序这是一个用户前端,另一个是管理面板 Web 前端,另一个是 REST API。这些中的每一个都是愿意进行不同配置的不同应用程序。这乘以几个环境(生产、预生产、测试​​、开发等)。这很容易在一家公司中产生 12 或 15 种配置。
    • @XaviMontero 我按照您的指示进行了第二种方法:当 var_dump $this->contact_email 或在函数 setConfig() 中添加 exit() 时,它不会退出。看起来 setConfig 没有被调用
    【解决方案3】:

    我要补充道格拉斯的答案,你可以访问全局配置,但是symfony会翻译一些参数,例如:

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

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

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

    【讨论】:

    • 请注意,参数在 symfony 3+ 中是私有的
    【解决方案4】:

    为了能够为您的包公开一些配置参数,您应该查阅相关文档。这很容易做到:)

    这是链接:How to expose a Semantic Configuration for a Bundle

    【讨论】:

    • 老实说,这个问题是2年前提出的,当时还没有上面的文章。
    【解决方案5】:

    就像之前所说的 - 您可以通过使用注入容器并使用其参数属性来访问任何参数。

    "Symfony - Working with Container Service Definitions" 是一篇关于它的好文章。

    【讨论】:

      【解决方案6】:

      我从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"));
          ...
          }
      

      【讨论】:

        猜你喜欢
        • 2011-11-28
        • 2014-04-24
        • 2012-04-30
        • 1970-01-01
        • 2013-11-24
        • 1970-01-01
        • 1970-01-01
        • 2010-12-30
        • 2012-08-29
        相关资源
        最近更新 更多