Как получить доступ к константам класса в Twig?

133

У меня есть несколько констант класса в моем классе сущности, например:

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

В обычном PHP я часто это делаю, if($var == Entity::TYPE_PERSON)и мне бы хотелось делать такие вещи в Twig. Является ли это возможным?

canni
источник

Ответы:

185
{% if var == constant('Namespace\\Entity::TYPE_PERSON') %}
{# or #}
{% if var is constant('Namespace\\Entity::TYPE_PERSON') %}

См. Документацию по constantфункции и constantтесту .

NikiC
источник
3
Вы должны добавить тестовые константы с экземпляром объекта в свой ответ{% if var is constant('TYPE_PERSON', object) %}
ioleo
1
Сработало, когда я набрал пространство имен, например сообщение @ message.
Crafter
232

Просто чтобы сэкономить ваше время. Если вам нужно получить доступ к константам класса в пространстве имен, используйте

{{ constant('Acme\\DemoBundle\\Entity\\Demo::MY_CONSTANT') }}
сообщение
источник
22
Важно отметить, что двойные косые черты важны. Я потратил несколько минут , потому что я не поставил двойной слеш.
Dan Morphis
Спасибо! вы экономите мое время! :)
sintetico82
7
Вау, это ужасно :-) Было бы неплохо, если бы Twig мог сделать константы похожими на другие свойства / переменные. например{% if var == object.MY_CONSTANT %}
Рик Хейвуд
27

Начиная с 1.12.1, вы также можете читать константы из экземпляров объектов:

{% if var == constant('TYPE_PERSON', entity)
Александр Федоров
источник
Это работает только в том случае, если объект является экземпляром Entity, я думаю, что вопрос заключается в доступе к константе без определенного объекта в шаблоне.
Sergi
В таком случае вы просто напишите {{ constant('Namespace\\Classname::CONSTANT_NAME') }}( док )
Александр Федоров
Что хорошо в этом, так это то, что он позволяет легко использовать переменную Twig вместо строкового литерала в качестве имени константы.
CJ Деннис
Просто для наглядности. Если вы хотите передать константы внутри класса как ветку vriable и использовать ее как {{ constant('TYPE_PERSON', entity) }}, можно сделать следующее (создать экземпляр класса Entity)$this->render('index.html.twig', ['entity' => new Entity()]);
Александр Цыганок
13

Изменить: я нашел лучшее решение, читайте об этом здесь.



Допустим, у вас есть класс:

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 }}
Дамиан Полак
источник
12
Таким образом, определение полного расширения ветки для каждого класса менее "уродливо", чем использование {{constant ('Acme \\ DemoBundle \\ Entity \\ Demo :: MY_CONSTANT')}}? А что вы делаете, когда имена ваших классов пересекаются? Вы теряете все преимущества пространства имен здесь
0x1gene
1
У меня есть аналогичное решение, но я мог бы извлечь его в связку. Проблема с этим решением в том, что у вас есть накладные расходы на отражение. В Symfony вы можете написать проход компилятора, чтобы разрешить это при компиляции контейнера.
Всем
@ 0x1gene Вы правы, имена классов могут перекрываться. Я молча предположил, что MyClass - это не просто какой-то класс, а класс, который очень важен в проекте. И используется достаточно часто, поэтому использование constant()с FQN будет утомительным.
Дамиан Полак
@DamianPolac Знаете ли вы, что PHPStorm предложит выбрать переменную в файле ветки?
Подиум
12

Если вы используете пространства имен

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

Важный! Используйте двойную косую черту вместо одиночной

Дмитрий Аполлонин
источник
9

В книге лучших практик Symfony есть раздел с этой проблемой:

Константы можно использовать, например, в шаблонах Twig благодаря функции constant ():

// 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

Chrysweel
источник
4

Через несколько лет я понял, что мой предыдущий ответ на самом деле не так хорош. Я создал расширение, которое лучше решает проблему. Он опубликован как открытый исходный код.

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

Он определяет новый оператор Twig, #который позволяет вам обращаться к константе класса через любой объект этого класса.

Используйте это так:

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

Дамиан Полак
источник
Спасибо за идею, никогда бы не подумал об этом! Если вы хотите использовать имена классов сущностей без экземпляров объектов, например User#TYPE_PERSON, то NodeExpressionкласс может быть изменен на что - то вроде этого, который работал для меня ->raw('(constant(\'App\\Entity\\' . $this->getNode('left')->getAttribute('name') . '::' . $this->getNode('right')->getAttribute('name') . '\'))'). Конечно, это ограничивает ваши классы App\Entityпространством имен, но я думаю, что это наиболее распространенный вариант использования.
futureal