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 "型一致";
}