จะเข้าถึงค่าคงที่ของคลาสใน Twig ได้อย่างไร?


133

ฉันมีค่าคงที่ของคลาสสองสามตัวในคลาสเอนทิตีของฉันเช่น:

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

ใน PHP ปกติฉันมักจะทำif($var == Entity::TYPE_PERSON)และฉันต้องการทำสิ่งนี้ใน Twig เป็นไปได้ไหม?

คำตอบ:


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

ดูเอกสารสำหรับconstantฟังก์ชั่นและการทดสอบconstant


3
คุณควรเพิ่มการทดสอบที่มีอินสแตนซ์วัตถุใน anwser ของคุณ{% if var is constant('TYPE_PERSON', object) %}
ioleo

1
ทำงานเมื่อฉันพิมพ์เนมสเปซเช่นข้อความของ @ ข้อความ
Crafter

232

เพียงเพื่อประหยัดเวลาของคุณ หากคุณต้องการเข้าถึงค่าคงที่ของคลาสภายใต้เนมสเปซให้ใช้

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

22
สิ่งสำคัญที่ควรทราบคือเครื่องหมายทับคู่มีความสำคัญ ผมเสียไม่กี่นาทีเพราะผมไม่ได้ใส่ทับขวาคู่ใน.
แดน Morphis

7
ว้าวน่าเกลียด :-) คงจะดีถ้า Twig ทำให้ค่าคงที่ดูเหมือนคุณสมบัติ / ตัวแปรอื่น ๆ เช่น{% if var == object.MY_CONSTANT %}
Rik Heywood

27

ตั้งแต่ 1.12.1 คุณสามารถอ่านค่าคงที่จากอินสแตนซ์ออบเจ็กต์ได้เช่นกัน:

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

สิ่งนี้ใช้ได้เฉพาะในกรณีที่เอนทิตีเป็นอินสแตนซ์ของเอนทิตีฉันคิดว่าคำถามเกี่ยวกับการเข้าถึงค่าคงที่โดยไม่มีวัตถุที่กำหนดไว้ในเทมเพลต
Sergi

ในกรณีนี้คุณเพียงแค่เขียน{{ constant('Namespace\\Classname::CONSTANT_NAME') }}( doc )
Alexander Fedorov

สิ่งที่ดีเกี่ยวกับเรื่องนี้คือทำให้ง่ายต่อการใช้ตัวแปร Twig แทนสตริงลิเทอรัลเป็นชื่อค่าคงที่
CJ Dennis

เพียงเพื่อความชัดเจน. หากคุณต้องการส่งผ่านค่าคงที่ภายในคลาสเป็น twig vriable และใช้มันอย่าง{{ constant('TYPE_PERSON', entity) }}นั้นคุณสามารถทำสิ่งต่อไปนี้ได้ (สร้างอินสแตนซ์เอนทิตีคลาส)$this->render('index.html.twig', ['entity' => new Entity()]);
Alexandr Tsyganok

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
ดังนั้นการกำหนดส่วนขยาย twig ทั้งหมดสำหรับแต่ละคลาสจึง "น่าเกลียด" น้อยกว่าการใช้ {{constant ('Acme \\ DemoBundle \\ Entity \\ Demo :: MY_CONSTANT')}}? แล้วคุณจะทำอย่างไรเมื่อชื่อชั้นของคุณทับซ้อนกัน? คุณสูญเสียประโยชน์ทั้งหมดของเนมสเปซที่นี่
0x1gene

1
ฉันมีวิธีแก้ปัญหาที่คล้ายกันฉันอาจแยกสิ่งนี้เป็นกลุ่มได้ ปัญหาในการแก้ปัญหานี้คือคุณมีค่าใช้จ่ายสะท้อน ในทางสัญลักษณ์คุณสามารถเขียนคอมไพเลอร์พาสเพื่อแก้ไขปัญหานี้เมื่อคอมไพล์คอนเทนเนอร์
ทุกคน

@ 0x1gene คุณพูดถูกชื่อคลาสสามารถทับซ้อนกันได้ ฉันคิดอย่างเงียบ ๆ ว่า MyClass ไม่ใช่แค่คลาสใด ๆ แต่เป็นคลาสที่มีความสำคัญมากในโปรเจ็กต์ และใช้บ่อยเพียงพอดังนั้นการใช้constant()กับ FQN จะน่ารำคาญ
Damian Polac

@DamianPolac คุณรู้หรือไม่ว่า PHPStorm จะแจ้งให้เลือกตัวแปรในไฟล์ทวิก
Codium

12

หากคุณใช้เนมสเปซ

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

สิ่งสำคัญ! ใช้เครื่องหมายทับคู่แทนการใช้เดี่ยว


9

ในหนังสือแนวทางปฏิบัติที่ดีที่สุดของ Symfony มีส่วนที่เกี่ยวข้องกับปัญหานี้:

ค่าคงที่สามารถใช้เป็นตัวอย่างในเทมเพลต Twig ของคุณได้โดยใช้ฟังก์ชัน constant ():

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

class Post
{
    const NUM_ITEMS = 10;

   // ...
}

และใช้ค่าคงที่นี้ในแม่แบบ twig:

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

ที่นี่ลิงค์: http://symfony.com/doc/current/best_practices/configuration.html#constants-vs-configuration-options


4

ผ่านไปหลายปีฉันก็รู้ว่าคำตอบก่อนหน้านี้ไม่ค่อยดีนัก ฉันได้สร้างส่วนขยายที่แก้ปัญหาได้ดีขึ้น เผยแพร่เป็นโอเพ่นซอร์ส

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

กำหนดตัวดำเนินการ Twig ใหม่#ซึ่งช่วยให้คุณเข้าถึงค่าคงที่ของคลาสผ่านวัตถุใด ๆ ของคลาสนั้น

ใช้แบบนั้น:

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


ขอบคุณสำหรับแนวคิดนี้ฉันไม่เคยคิดแบบนี้มาก่อน! หากคุณต้องการที่จะใช้ชื่อชั้นนิติบุคคลโดยไม่ต้อง instantiating วัตถุตัวอย่างUser#TYPE_PERSONที่ระดับอาจมีการเปลี่ยนแปลงบางสิ่งบางอย่างเช่นนี้ซึ่งทำงานให้ฉัน:NodeExpression ->raw('(constant(\'App\\Entity\\' . $this->getNode('left')->getAttribute('name') . '::' . $this->getNode('right')->getAttribute('name') . '\'))')แน่นอนว่าสิ่งนี้ จำกัด ชั้นเรียนของคุณไว้ที่App\Entityเนมสเปซ แต่ฉันคิดว่ามันครอบคลุมกรณีการใช้งานที่พบบ่อยที่สุด
อนาคต
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.