squirrelphp/twig-php-syntax

将常见PHP语法添加到Twig模板中,如 ===、foreach 和 continue/break。

v1.8 2024-05-01 12:16 UTC

This package is auto-updated.

Last update: 2024-08-31 00:26:36 UTC


README

Build Status Test Coverage PHPStan Packagist Version PHP Version Software License

启用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中中断循环可能很方便,但并没有原生支持。此库添加了breakcontinue,并且它们与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中规避breakcontinue的使用,但它有时会导致额外的嵌套和更复杂的代码。仅仅一个breakcontinue就可以澄清这些情况中的行为和意图。然而,我建议谨慎使用breakcontinue

变量类型测试(字符串、数组、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。这可能是这个库中最不有用的一部分,因为andor已经很短且清晰,但这是另一个容易解决的 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 %}