如何从 Symfony2 config.yml 读取配置设置?
Posted
技术标签:
【中文标题】如何从 Symfony2 config.yml 读取配置设置?【英文标题】:How do I read configuration settings from 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 重新加载的站点文档,但我不知道如何做到这一点。
现在可能只是太累了,无法弄清楚。有人可以帮忙吗?
【问题讨论】:
【参考方案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"));
...
【讨论】:
以上是关于如何从 Symfony2 config.yml 读取配置设置?的主要内容,如果未能解决你的问题,请参考以下文章