Jak uzyskać dostęp do stałych klas w Twig?

133

W mojej klasie encji mam kilka stałych klas, np .:

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

W zwykłym PHP często robię if($var == Entity::TYPE_PERSON)i chciałbym robić tego typu rzeczy w Twig. Czy to możliwe?

canni
źródło

Odpowiedzi:

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

Zobacz dokumentację dotyczącą constantfunkcji i constanttestu .

NikiC
źródło
3
Powinieneś dodać testowanie z instancją obiektu do swojego {% if var is constant('TYPE_PERSON', object) %}
anwser
1
Działało, gdy wpisałem przestrzeń nazw, na przykład wiadomość @ wiadomość.
crafter
232

Żeby zaoszczędzić czas. Jeśli potrzebujesz uzyskać dostęp do stałych klas w przestrzeni nazw, użyj

{{ constant('Acme\\DemoBundle\\Entity\\Demo::MY_CONSTANT') }}
wiadomość
źródło
22
Należy zauważyć, że podwójne ukośniki są ważne. Zmarnowałem kilka minut, ponieważ nie wstawiłem podwójnego ukośnika.
Dan Morphis
Dziękuję Ci! oszczędzasz mój czas! :)
sintetico82
7
Wow, to brzydkie :-) Byłoby miło, gdyby Twig mógł sprawić, by stałe wyglądały jak inne właściwości / zmienne. np.{% if var == object.MY_CONSTANT %}
Rik Heywood
27

Od wersji 1.12.1 można również odczytywać stałe z instancji obiektów:

{% if var == constant('TYPE_PERSON', entity)
Aleksandra Fiodorowa
źródło
Działa to tylko wtedy, gdy entity jest instancją Entity, myślę, że pytanie dotyczy dostępu do stałej bez zdefiniowanego obiektu w szablonie.
Sergi
W takim razie po prostu napisz {{ constant('Namespace\\Classname::CONSTANT_NAME') }}( doc )
Alexander Fedorov,
Zaletą tego jest to, że ułatwia użycie zmiennej Twig zamiast literału ciągu jako nazwy stałej.
CJ Dennis
Tylko dla jasności. Jeśli chcesz przekazać stałe w klasie jak gałązka vriable i używać go jak {{ constant('TYPE_PERSON', entity) }}jest to możliwe do zrobienia następujące (instancję klasy Entity)$this->render('index.html.twig', ['entity' => new Entity()]);
Alexandr Tsyganok
13

Edycja: znalazłem lepsze rozwiązanie, przeczytaj o tym tutaj.



Powiedzmy, że masz klasę:

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

Utwórz i zarejestruj rozszerzenie 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
        );
    }
}

Teraz możesz używać stałych w Twig, takich jak:

{{ MyClass.MY_CONSTANT }}
Damian Polac
źródło
12
Zatem zdefiniowanie całego rozszerzenia gałązki dla każdej klasy jest mniej "brzydkie" niż użycie {{stałej ('Acme \\ DemoBundle \\ Entity \\ Demo :: MY_CONSTANT')}}? A co robisz, gdy nazwy klas się pokrywają? tracisz tutaj wszystkie zalety przestrzeni nazw
0x1gene
1
Mam podobne rozwiązanie, ale mógłbym wyodrębnić to do pakietu. Problem z tym rozwiązaniem polega na tym, że masz nad głową odbicie. W symfony możesz napisać przebieg kompilatora, aby rozwiązać ten problem podczas kompilacji kontenera.
Ktoś
@ 0x1gene Masz rację, nazwy klas mogą się nakładać. Po cichu założyłem, że MyClass to nie byle jaka klasa, ale klasa, która jest bardzo ważna w projekcie. I używany na tyle często, że używanie constant()z FQN byłoby uciążliwe.
Damian Polac
@DamianPolac czy wiesz, że PHPStorm poprosi o wybór zmiennej w pliku twig?
Codium
12

Jeśli używasz przestrzeni nazw

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

Ważny! Użyj podwójnych ukośników zamiast pojedynczych

Dmitriy Apollonin
źródło
9

W książce o najlepszych praktykach Symfony znajduje się sekcja z tym problemem:

Stałe mogą być używane na przykład w twoich szablonach Twig dzięki funkcji constant ():

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

class Post
{
    const NUM_ITEMS = 10;

   // ...
}

I użyj tej stałej w gałązce szablonu:

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

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

Chrysweel
źródło
4

Po kilku latach zdałem sobie sprawę, że moja poprzednia odpowiedź nie jest zbyt dobra. Stworzyłem rozszerzenie, które lepiej rozwiązuje problem. Jest opublikowany jako open source.

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

Definiuje nowy operator Twig, #który umożliwia dostęp do stałej klasy poprzez dowolny obiekt tej klasy.

Użyj tego w ten sposób:

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

Damian Polac
źródło
Dzięki za pomysł, nigdy o tym nie pomyślałem! Jeśli chcesz używać nazw klas podmiot bez instancji obiektów, na przykład User#TYPE_PERSONThe NodeExpressionklasa może zostać zmieniona na czymś takim, który pracował dla mnie ->raw('(constant(\'App\\Entity\\' . $this->getNode('left')->getAttribute('name') . '::' . $this->getNode('right')->getAttribute('name') . '\'))'). Oczywiście ogranicza to twoje klasy do App\Entityprzestrzeni nazw, ale myślę, że obejmuje to najbardziej powszechny przypadek użycia.
Futureal