LoginSignup
1
0

More than 5 years have passed since last update.

Symfony2のTwigでinstanceofを使えるようにする

Last updated at Posted at 2014-07-30

Twigテンプレート内でinstanceofを使って分岐する必要があったので、
Twig拡張機能を利用してinstanceof演算子を作成しました。

作る

演算子のパーサーを作成

TwigNodeExpressionBinaryInstanceof.php
<?php

namespace MyApp\SomeBundle\Twig\Node\Expression\Binary;

class TwigNodeExpressionBinaryInstanceof extends \Twig_Node_Expression_Binary
{
    /**
     * {@inheritdoc}
     */
    public function compile(\Twig_Compiler $compiler)
    {
        $id = uniqid();

        // 「$some instanceof 'クラス名'」が不可能なので
        // 「(($class = 'クラス名') && ($some instanceof $class))」にする
        $compiler
            ->raw("((\$_{$id} = ")
            ->subcompile($this->getNode('right'))
            ->raw(') && (')
            ->subcompile($this->getNode('left'))
            ->raw(" instanceof \$_{$id}))")
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function operator(\Twig_Compiler $compiler)
    {
        $compiler->raw('');
    }
}

Twig拡張を作成&演算子を定義

MyTwigExtension.php
<?php

namespace MyApp\SomeBundle\Twig\Extension;

class MyTwigExtension extends \Twig_Extension
{
    /**
     * {@inheritdoc}
     */
    public function getOperators()
    {
        return [
            [/* 単項演算子を定義 */],
            [/* 二項演算子を定義 */
                'instanceof' => [
                    'precedence' => 100,
                    'class' => 'MyApp\SomeBundle\Twig\Node\Expression\Binary\TwigNodeExpressionBinaryInstanceof',
                    'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT
                ],
            ],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'my_twig_extension';
    }
}

Twig拡張をサービスに登録

services.yml
services:
    my_app_some.twig.extension:
        class: MyApp\SomeBundle\Twig\MyTwigExtension
        tags:
            - { name: twig.extension }

使う

Twigテンプレート内の条件式にinstanceofが使用できます。

some_template.html.twig
{% if some_variable instanceof 'MyApp\\SomeBundle\\Entity\\SomeEntityClass' %}
    型一致
{% endif %}

キャッシュを確認すると下記のように変換されていることがわかります。

11f5066ea180e1890490269413e0673a7e6b69697f9fd625e0b13a7f729b.php
if ((($_53d8f5ab4ca6d = "MyApp\\SomeBundle\\Entity\\SomeEntityClass") && ((isset($context["some_variable"]) ? $context["some_variable"] : $this->getContext($context, "some_variable")) instanceof $_53d8f5ab4ca6d))) {
    echo "型一致";
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0