Symfony2 在 YAML 配置中使用 PHP 类常量?

Posted

技术标签:

【中文标题】Symfony2 在 YAML 配置中使用 PHP 类常量?【英文标题】:Symfony2 Use PHP Class Constant in YAML Config? 【发布时间】:2013-01-20 18:09:24 【问题描述】:

我知道这可能是不可能的,但是有没有一种干净的方法可以在 YAML 配置/服务/等中使用 php 类常量。 Symfony2 的文件?

例如,如果我有这个:

namespace My\Bundle\DependencyInjection;

class MyClass

    const MY_CONST = 'cookies';

这样的事情可能吗(在 .yml 文件中):

services:
    my_service:
        class: Some\Class
        arguments:
            - %My\Bundle\DependencyInjection\MyClass::MY_CONST%

这将大大有助于保持两者之间的一致性。

【问题讨论】:

你为什么不注入类然后访问你的服务中的常量或者将它的值作为参数添加到你的配置中并将它注入你的类以及你的服务中?无论如何,您可能想查看 OpenSky 的 RuntimeConfigBundle github.com/opensky/OpenSkyRuntimeConfigBundle>,它允许您将参数动态注入到您的配置中。文档有点稀缺,但应该足以让您入门。 我不希望设置之类的东西影响我以这种方式编写代码的方式(它会给我留下不好的印象)。我也不想在运行时注入它们,因为那样它就不能利用缓存。 【参考方案1】:
arguments:
      - key_1: "value_1"
        !php/const App\Example::CONSTANT_1: 'value_0'

github issue: Using a PHP class constant for a key in a YAML hash

【讨论】:

【参考方案2】:

从 Symfony 3.2 开始,还可以使用特殊的 !php/const: 语法在 YAML 文件中使用 PHP 常量:

parameters:
    bar: !php/const:PHP_INT_MAX

有关详细信息,请参阅Symfony blog post。


请注意:在 Symfony 4 中,语法为 was slightly changed。您必须使用空格而不是双冒号,例如:

parameters:
    bar: !php/const PHP_INT_MAX

否则,您将收到带有消息“注意:未初始化的字符串偏移”的 FileLoaderLoadException。

【讨论】:

谢谢@d70rr3s :) 也可能不是那么明显,你可以把类常量放在那里,因为几乎每个示例都使用全局空间常量。【参考方案3】:

应该可以在配置和类__construct($constant1) 中将参数作为纯“文本”插入,然后通过constant($constant1) 函数通过变量请求常量。

但是我不确定这里的全局常量,因为它们可能在使用时没有定义,但是对于具有整个命名空间的类常量来说应该不是问题,因为命名空间定位器在调用时已经定义了类。

示例配置:

services:
    my_service:
        class: Some\Class
    arguments:
        - 'My\Bundle\DependencyInjection\MyClass::MY_CONST'

和示例类方法:

public function __construct($arg1)

    $myRequiredConstantValue = constant($arg1);

【讨论】:

【参考方案4】:

在 Symfony 3.2 之前的版本中,注入 PHP 常量仅适用于 XML:

<parameter key="my_service.my_const" type="constant">My\Bundle\DependencyInjection\MyClass::MY_CONST</parameter>

如果你想保留你的 yml 文件,你可以将 xml 文件导入到你的 services.yml 中。混合配置样式可能有点难看,但据我所知这是唯一的方法。

如果这对您不起作用,我对您的问题的评论适用。

【讨论】:

您也可以使用 PHP 代替 XML。添加 PHP 导入文件为您提供了很大的灵活性,只要记住 Ben Parker 叔叔,并为这个强大的力量负责! 有关食谱中的参考,请参阅symfony.com/doc/current/components/dependency_injection/…【参考方案5】:

对于 Symfony >=2.4,您可以使用 expression language

例子:

'@=constant("Symfony\\Bridge\\Monolog\\Logger::INFO")'

【讨论】:

你有没有成功使用表达式语言作为属性的值?例如,当defining an event listener 通过服务标签: name: kernel.event_listener, event: '@constant("\\App\\Namespace\\Class::Constant")', method: someEvent 。在我自己的尝试中,该表达式似乎从未被评估过。想在发帖之前先问一下! Tripe slashes 在我的例子中有效,例如“@=constant('\\\Symfony\\\Bridge\\\Monolog\\\Logger::INFO')”,不是单一的也不是双重的 【参考方案6】:

这是可能的,但只有在使用 eval'd 代码时才会这样做,这通常是不受欢迎的。

给定一个类常量 Permission::ACCESS_NONE 例如你可以在 yaml 文件中做这样的事情:

permission: ACCESS_NONE

以及解析 yaml 的代码中的以下内容:

eval("return \The\Complete\Namespace\To\Permission::".$context['permission'].";");

这当然是丑陋的代码,但它确实有效。

【讨论】:

请记住,eval() 之类的功能可能会在大多数生产环境中被禁用,因为它可能会导致安全问题。【参考方案7】:

这应该可行

arguments:
 - <?php echo My\Bundle\DependencyInjection\MyClass::MY_CONST."\n" ?>

【讨论】:

是吗?供您参考:Yaml introduction、Source code。甚至在Recent security release 中也提到过 @jonhattan 告诉我我是否错了,但默认情况下,yaml 不会评估 php 对吗? 以上在 Symfony 1.4 中可以工作。我不知道 Sf2.1。 好吧,我很抱歉当时这么苛刻。但是,它似乎很不安全,只能以非常规的方式使用。 Yaml::parse() 可以评估 .yml 文件中的 php 代码 (when enabled)。如果你想这样做(我确信有商业用例可以这样做),那么你需要导入一个 php 配置文件(使用'imports:')。这使您可以将 yml 用于大多数事情,但 PHP 用于您可能需要它的位。在 php 中,您可以访问容器并执行以下操作:$container-&gt;setParameter('foo.bar', FOO_BAR);,其中 FOO_BAR 是 php 常量或其他一些严肃的 Symfonians 会皱眉头的老派顽皮东西。

以上是关于Symfony2 在 YAML 配置中使用 PHP 类常量?的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2中Yaml中的参数作为数组

在 Symfony2 中将多维数组转换为点表示法

使用 YAML 的 Doctrine2 和 Symfony2 的默认列值?

使用 Monolog 在 Symfony2 中记录 PHP 致命错误

学习PHP中YAML操作扩展的使用

Symfony2功能测试用例不包括自定义依赖注入配置参数