154

I have a few class constants in my entity class, e.g.:

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

In normal PHP I often do if($var == Entity::TYPE_PERSON) and I would like to do this kind of stuff in Twig. Is it possible?

NikiC
  • 100,734
  • 37
  • 191
  • 225
canni
  • 5,737
  • 9
  • 46
  • 68

7 Answers7

251

Just to save your time. If you need to access class constants under namespace, use

{{ constant('Acme\\DemoBundle\\Entity\\Demo::MY_CONSTANT') }}
message
  • 4,513
  • 2
  • 28
  • 39
212
{% if var == constant('Namespace\\Entity::TYPE_PERSON') %}
{# or #}
{% if var is constant('Namespace\\Entity::TYPE_PERSON') %}

See documentation for the constant function and the constant test.

frzsombor
  • 2,274
  • 1
  • 22
  • 40
NikiC
  • 100,734
  • 37
  • 191
  • 225
34

As of 1.12.1 you can read constants from object instances as well:

{% if var == constant('TYPE_PERSON', entity)
alexfv
  • 1,826
  • 2
  • 19
  • 22
  • This only works if entity is an instance of Entity, I think that the question is about accessing a constant without a defined object in the template. – Sergi Feb 03 '16 at 15:38
  • In that case you just write `{{ constant('Namespace\\Classname::CONSTANT_NAME') }}` ([doc](http://twig.sensiolabs.org/doc/functions/constant.html)) – alexfv Feb 03 '16 at 16:12
  • What's good about this is that it makes it easy to use a Twig variable instead of a string literal as the constant name. – CJ Dennis Jun 06 '18 at 01:45
  • Just for clarity. If you want to pass constants within a class as twig vriable and use it like `{{ constant('TYPE_PERSON', entity) }}`, it's possible to do following (instantiate Entity class) `$this->render('index.html.twig', ['entity' => new Entity()]);` – Alexandr Tsyganok Apr 23 '19 at 20:05
  • I wonder if you can use `constant('SOME_CONSTANT', form.getFoo())` where `getFoo()` returns the custom FormType PHP class. – rybo111 Feb 22 '22 at 14:11
13

If you are using namespaces

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

Important! Use double slashes, instead of single

Dmitriy Apollonin
  • 1,418
  • 2
  • 16
  • 30
12

Edit: I've found better solution, read about it here.



Let's say you have class:

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

Create and register Twig extension:

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
        );
    }
}

Now you can use constants in Twig like:

{{ MyClass.MY_CONSTANT }}
Community
  • 1
  • 1
Damian Polac
  • 911
  • 9
  • 20
  • 15
    So defining a entire twig extension for each class is less "ugly" than using {{ constant('Acme\\DemoBundle\\Entity\\Demo::MY_CONSTANT') }} ? And what do you do when your class names overlaps ? you loose all the benefit of namespaces here – 0x1gene Aug 27 '15 at 20:37
  • 1
    I have a similar solution, I might extract this to a bundle though. The problem with this solution is that you have reflection overhead. In symfony you can write a compiler pass to resolve this when the container is compiled. – Anyone Jan 15 '16 at 08:06
  • @0x1gene You are right, class names can overlap. I silently assumed that MyClass is not just any class, but a class which is very important within project. And used often enough so using `constant()` with FQN would be bothersome. – Damian Polac May 21 '16 at 19:48
  • @DamianPolac do you know PHPStorm will prompt variable selection in twig file? – Codium Jun 21 '20 at 08:38
  • When you say "Now", you should probably be more specific what version you're referring to. – Colandus Feb 24 '23 at 09:35
11

In book best practices of Symfony there is a section with this issue:

Constants can be used for example in your Twig templates thanks to the constant() function:

// src/AppBundle/Entity/Post.php
namespace AppBundle\Entity;

class Post
{
    const NUM_ITEMS = 10;

   // ...
}

And use this constant in template twig:

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

Here the link: http://symfony.com/doc/current/best_practices/configuration.html#constants-vs-configuration-options

Chrysweel
  • 363
  • 4
  • 8
4

After some years I realized that my previous answer is not really so good. I have created extension that solves problem better. It's published as open source.

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

It defines new Twig operator # which let you access the class constant through any object of that class.

Use it like that:

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

Damian Polac
  • 911
  • 9
  • 20
  • Thanks for the idea, I'd never thought of this! If you'd like to use entity class names without instantiating objects, for example `User#TYPE_PERSON`, the `NodeExpression` class could be changed to something like this, which worked for me: `->raw('(constant(\'App\\Entity\\' . $this->getNode('left')->getAttribute('name') . '::' . $this->getNode('right')->getAttribute('name') . '\'))')`. Of course, this limits your classes to the `App\Entity` namespace, but I think that covers the most common use case. – futureal May 19 '18 at 16:59