【问题标题】:How to access class constants in Twig?如何访问 Twig 中的类常量?
【发布时间】:2011-11-28 11:49:06
【问题描述】:

我的实体类中有一些类常量,例如:

class Entity {
    const TYPE_PERSON = 0;
    const TYPE_COMPANY = 1;
}

在普通的 PHP 中,我经常使用if($var == Entity::TYPE_PERSON),我想在 Twig 中做这种事情。有可能吗?

【问题讨论】:

    标签: php templates twig


    【解决方案1】:

    只是为了节省您的时间。如果需要访问命名空间下的类常量,请使用

    {{ constant('Acme\\DemoBundle\\Entity\\Demo::MY_CONSTANT') }}
    

    【讨论】:

    • 注意双斜线很重要。我浪费了几分钟,因为我没有输入双反斜杠。
    • 哇,太丑了 :-) 如果 Twig 可以使常量看起来像其他属性/变量,那就太好了。例如{% if var == object.MY_CONSTANT %}
    【解决方案2】:
    {% if var == constant('Namespace\\Entity::TYPE_PERSON') %}
    {# or #}
    {% if var is constant('Namespace\\Entity::TYPE_PERSON') %}
    

    请参阅constant functionconstant test 的文档。

    【讨论】:

    • 您应该将带有对象实例的测试内容添加到您的 anwser {% if var is constant('TYPE_PERSON', object) %}
    • 在我输入命名空间时工作,例如@message 的消息。
    【解决方案3】:

    从 1.12.1 开始,您也可以从对象实例中读取常量:

    {% if var == constant('TYPE_PERSON', entity)
    

    【讨论】:

    • 这仅适用于实体是实体的实例,我认为问题是关于访问模板中没有定义对象的常量。
    • 在这种情况下你只需写{{ constant('Namespace\\Classname::CONSTANT_NAME') }} (doc)
    • 这样做的好处是它可以很容易地使用 Twig 变量而不是字符串文字作为常量名。
    • 只是为了清楚起见。如果您想将类中的常量作为 twig vriable 传递并像{{ constant('TYPE_PERSON', entity) }} 一样使用它,则可以执行以下操作(实例化实体类)$this->render('index.html.twig', ['entity' => new Entity()]);
    • 我想知道你是否可以使用constant('SOME_CONSTANT', form.getFoo()) getFoo() 返回自定义FormType PHP 类。
    【解决方案4】:

    如果您使用命名空间

    {{ constant('Namespace\\Entity::TYPE_COMPANY') }}
    

    重要!使用双斜杠,而不是单斜杠

    【讨论】:

      【解决方案5】:

      编辑:我找到了更好的解决方案,read about it here.



      假设你有课:

      namespace MyNamespace;
      class MyClass
      {
          const MY_CONSTANT = 'my_constant';
          const MY_CONSTANT2 = 'const2';
      }
      

      创建和注册 Twig 扩展:

      class MyClassExtension extends \Twig_Extension
      {
          public function getName()
          { 
              return 'my_class_extension'; 
          }
      
          public function getGlobals()
          {
              $class = new \ReflectionClass('MyNamespace\MyClass');
              $constants = $class->getConstants();
      
              return array(
                  'MyClass' => $constants
              );
          }
      }
      

      现在您可以在 Twig 中使用常量,例如:

      {{ MyClass.MY_CONSTANT }}
      

      【讨论】:

      • 所以为每个类定义一个完整的 twig 扩展比使用 {{ constant('Acme\\DemoBundle\\Entity\\Demo::MY_CONSTANT') }} 更“难看”?当你的类名重叠时你会怎么做?你在这里失去了命名空间的所有好处
      • 我有一个类似的解决方案,不过我可能会将它提取到一个包中。这个解决方案的问题是你有反射开销。在 symfony 中,您可以编写编译器传递来在编译容器时解决此问题。
      • @0x1gene 你说得对,类名可以重叠。我默默地假设 MyClass 不仅仅是任何类,而是一个在项目中非常重要的类。并且经常使用,因此将 constant() 与 FQN 一起使用会很麻烦。
      • @DamianPolac 你知道 PHPStorm 会在 twig 文件中提示变量选择吗?
      【解决方案6】:

      在 Symfony 的最佳实践中,有一节涉及此问题:

      得益于 constant() 函数,例如可以在 Twig 模板中使用常量:

      // src/AppBundle/Entity/Post.php
      namespace AppBundle\Entity;
      
      class Post
      {
          const NUM_ITEMS = 10;
      
         // ...
      }
      

      并在模板树枝中使用此常量:

      <p>
          Displaying the {{ constant('NUM_ITEMS', post) }} most recent results.
      </p>
      

      这里是链接: http://symfony.com/doc/current/best_practices/configuration.html#constants-vs-configuration-options

      【讨论】:

        【解决方案7】:

        几年后,我意识到我之前的答案并不是那么好。我创建了可以更好地解决问题的扩展。它以开源形式发布。

        https://github.com/dpolac/twig-const

        它定义了新的 Twig 操作符#,它允许您通过该类的任何对象访问该类常量。

        像这样使用它:

        {% if entity.type == entity#TYPE_PERSON %}

        【讨论】:

        • 感谢您的想法,我从来没有想过这个!如果您想在不实例化对象的情况下使用实体类名称,例如User#TYPE_PERSON,则可以将NodeExpression 类更改为这样的名称,这对我有用:-&gt;raw('(constant(\'App\\Entity\\' . $this-&gt;getNode('left')-&gt;getAttribute('name') . '::' . $this-&gt;getNode('right')-&gt;getAttribute('name') . '\'))')。当然,这会将您的类限制为 App\Entity 命名空间,但我认为这涵盖了最常见的用例。
        猜你喜欢
        • 2021-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-08
        • 2011-09-19
        • 1970-01-01
        • 2014-06-10
        相关资源
        最近更新 更多