squirrelphp / twig-php-syntax
将常见PHP语法添加到Twig模板中,如 ===、foreach 和 continue/break。
Requires
- php: >=7.2.5
- twig/twig: ^3.9
Requires (Dev)
- bamarni/composer-bin-plugin: ^1.3
- captainhook/plugin-composer: ^5.0
- phpunit/phpunit: ^10.0
README
启用PHP中已知的语法,以便PHP开发者可以更容易地创建和编辑Twig模板。这对于小型项目特别有用,在这些项目中,PHP开发者最终会编写Twig模板,而且模板中的语法略有不同并不值得。
安装
composer require squirrelphp/twig-php-syntax
配置
将PhpSyntaxExtension添加到Twig
$twig = new \Twig\Environment($loader); $twig->addExtension(new \Squirrel\TwigPhpSyntax\PhpSyntaxExtension());
您还可以查看扩展定义并创建自己的扩展类,仅包含一些功能,如果您不喜欢所有功能。
Symfony集成
如果您使用 autoconfigure(这是默认设置),您只需要在项目的 config 目录中的 services.yaml 文件中加载 PhpSyntaxExtension 类(前四行应该已经存在,只需在文件末尾添加包含 PhpSyntaxExtension 类的行)
services: _defaults: autowire: true autoconfigure: true # Just add the following line, Symfony will register # the extension in Twig for you if Twig is installed Squirrel\TwigPhpSyntax\PhpSyntaxExtension: ~
如果您不使用 autoconfigure,您可以将twig扩展标签添加到服务定义中
services: Squirrel\TwigPhpSyntax\PhpSyntaxExtension: tags: - { name: twig.extension }
功能
=== / !== 严格比较运算符
Twig有same as测试,它模仿PHP中的===,但语法可能难以适应。使用PHP中的严格比较运算符(===和!==)可以减少摩擦,更熟悉且更简洁。
{% if 1 === 1 %}
This will be shown
{% endif %}
{% if 1 is same as(1) %}
Same as above but with standard Twig syntax
{% endif %}
{% if 1 === '1' %}
This will not be shown, as 1 and '1' have different types (string vs. integer)
{% endif %}
{% if somevariable === "test" %}
somevariable is of type string and equals "test"
{% endif %}
{% if somevariable !== "test" %}
somevariable either is not a string or does not equal "test"
{% endif %}
strtotime过滤器
当数据只有(日期)字符串时,在模板中比较时间戳在Twig中有些繁琐,因为没有strtotime过滤器 - 此库添加了它,与PHP中的完全相同
{% if "2018-05-05"|strtotime > "2017-05-05"|strtotime %}
This is always true, as 2018 results in a larger timestamp integer than 2017
{% endif %}
{% if post.date|strtotime > otherpost.date|strtotime %}
Compares the dates of post and otherpost. strtotime returns an integer
or throws an InvalidArgumentException if strtotime returns false
{% endif %}
{# Sets next thursday as a timestamp variable, but also sets "now"
like in strtotime in PHP to define from where the timestamp is
calculated if it is a relative date and not an absolute date #}
{% set nextThusday = "next Thursday"|strtotime(now=sometimestamp) %}
foreach循环
Twig使用for来创建循环,其语法与PHP中的foreach略有不同。使用此库,foreach在Twig中以与PHP相同的语法可用
{% foreach list as sublist %}
{% foreach sublist as key => value %}
{% endforeach %}
{% endforeach %}
它在内部行为完全相同:for实际上创建ForNode元素,因此您具有与for循环相同的功能,包括循环变量和else。与for一样,else的行为相同。
{% foreach list as sublist %}
{% foreach sublist as key => value %}
{% else %}
Array "sublist" is empty / no iteration took place
{% endforeach %}
{% else %}
Array "list" is empty / no iteration took place
{% endforeach %}
break和continue
有时在Twig中中断循环可能很方便,但并没有原生支持。此库添加了break和continue,并且它们与PHP中的行为完全相同
{% foreach list as entry %}
{% if loop.index > 10 %}
{% break %}
{% endif %}
{% endforeach %}
您可以使用break与一个数字来跳出多个循环,就像在PHP中一样:(continue不支持此操作)
{% foreach list as sublist %}
{% foreach sublist as entry %}
{% if loop.index > 10 %}
{% break 2 %} {# breaks out of both foreach loops #}
{% endif %}
{% endforeach %}
{% endforeach %}
虽然您通常可以在Twig中规避break和continue的使用,但它有时会导致额外的嵌套和更复杂的代码。仅仅一个break或continue就可以澄清这些情况中的行为和意图。然而,我建议谨慎使用break和continue。
变量类型测试(字符串、数组、true、callable等)
添加了PHP中已知的测试,因此您可以测试一个值是否为
- 数组(如
is_array) - 布尔值(如
is_bool) - 可调用(如
is_callable) - 浮点数(如
is_float) - 整数(如
is_int) - 对象(如
is_object) - 一个标量(整数、浮点数、字符串或布尔值,例如
is_scalar) - 一个字符串(例如
is_string) - 真(例如
=== true) - 假(例如
=== false)
它内部使用所提到的PHP函数/比较,因此与PHP中的行为相同。
{% if someflag is true %} {# instead of {% if someflag is same as(true) %} #}
{% endif %}
{% if someflag is false %} {# instead of {% if someflag is same as(false) %} #}
{% endif %}
{% if somevar is string %} {# no equivalent in Twig %} #}
{% endif %}
{% if somevar is scalar %} {# no equivalent in Twig %} #}
{% endif %}
{% if somevar is object %} {# no equivalent in Twig %} #}
{% endif %}
{% if somevar is integer %} {# no equivalent in Twig %} #}
{% endif %}
{% if somevar is int %} {# same as integer test above, alternate way to write it %} #}
{% endif %}
{% if somevar is float %} {# no equivalent in Twig %} #}
{% endif %}
{% if somevar is callable %} {# no equivalent in Twig %} #}
{% endif %}
{% if somevar is boolean %} {# no equivalent in Twig %} #}
{% endif %}
{% if somevar is bool %} {# same as boolean test above, alternate way to write it %} #}
{% endif %}
{% if somevar is array %} {# no equivalent in Twig %} #}
{% endif %}
转换为类型:intval、strval、floatval和boolval过滤器
将变量转换为特定类型不是Twig所鼓励的,如果可能的话,应该避免这样做。然而,有些情况下,你可能只是想将某些内容转换为整数或字符串,以确保比较是类型安全的,或者没有由于类型错误而产生的意外行为。
{% if '5'|intval === 5 %}
Convert '5' to an integer - this if block is being executed
{% endif %}
{% if 5.7|strval === '5.7' %}
Convert 5.7 to a string - this if block is being executed
{% endif %}
{% if 1|boolval === true %}
Convert 1 to a boolean - this if block is being executed
{% endif %}
{% if '5.7'|floatval === 5.7 %}
Convert '5.7' to a float - this if block is being executed
{% endif %}
这些过滤器的主要行为与PHP中的过滤器类似(并内部使用相应的PHP函数),但有一些额外的行为来检测或避免可能出现的错误。
- 只允许标量值、null和具有__toString方法的对象,因此如果你使用任何这些过滤器与数组或无法转换为字符串的对象,将会抛出异常。
- null对于intval返回0,对于strval返回'',对于boolval返回false,对于floatval返回0.0(就像在PHP中一样)。
- 具有__toString方法的对象将首先被转换为字符串(使用__toString方法),然后才会使用intval、boolval和floatval。
- boolval应该谨慎使用,因为如果你给它任何非数字字符串,它将返回true,而空字符串和"0"将返回false。boolval在这里更多是为了完整性,因为可能是PHP中用途最少的转换函数。建议如果可能的话,使用其他三个函数而不是使用boolval。
&& 和 ||
如果你想使表达式更像PHP,可以使用&&代替and,使用||代替or。这可能是这个库中最不有用的一部分,因为and和or已经很短且清晰,但这是另一个容易解决的 Twig 和 PHP 之间的差异,而且&&和||在比较时可能更容易被发现。
{% if someflag === true && otherflag === false %}
instead of if someflag === true and otherflag === false
{% endif %}
{% if someflag === true || otherflag === true %}
instead of if someflag === true or otherflag === false
{% endif %}