twig模板引擎详解(上集:设计师篇)【twig模板引擎中文使用教程】

版权声明:本文为云客原创,转载须注明出处,微信号:php-world,qq群203286137,欢迎留言 https://blog.csdn.net/u011474028/article/details/81086725

前文:本文是《云客drupal源码分析》系列的番外篇,由于drupal采用了twig模板引擎,因此该篇将详细介绍twig,但不会涉及drupal任何内容,是原生twig的使用详解,分上下两集,上集供设计师阅读,讲解在模板中的使用,下集供php程序开发人员阅读,讲解程序调用、扩展开发。

本篇为上集,额外介绍了安装等必要内容,以便首次接触人员查阅,纯模板设计师可以跳过。
官网地址:https://twig.symfony.com/
本文写作时官网已经发布了V1.35.3 及V2.4.8

安装:
需求:
和php一样,发布大版本后,以前的版本依然会维护一段时间,因此twig目前有两个版本都在维护
1.X版本:至少PHP 5.2.7,从1.34开始至少需要PHP 5.3.3.
2.X版本:至少PHP 7.0.0

包括drupal8在内,许多项目都还在使用1.X,这里以1.X做主要介绍,有多种方法安装twig,官方推荐使用composer,运行如下命令即可:

composer require twig/twig:~1.0

为了提高性能twig还提供了有限功能的php层面的C扩展,详见官网,这里我们以下载文件方式来安装。

安装:

到这里下载文件包:https://github.com/twigphp/Twig/tags

本文选择: v1.35.3  解压下载的Twig-1.35.3.tar.gz  由于twig使用psr-0的自动加载方式,所以里面的lib就是我们需要的库文件,将其复制到网站根目录即可

你可以在本机通过phpstudy等软件安装运行环境,这里以C:\root\twigtest作为网站根目录,以http://www.twigtest.com/作为域名

根目录建立index.php,内容如下:
 

<?php
require_once 'lib/Twig/Autoloader.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_Array(array(
    'index' => 'Hello {{ name }}!',
));
$twig = new Twig_Environment($loader);
echo $twig->render('index', array('name' => 'Fabien'));

访问域名,即可看到结果,安装完成。

开始使用:

假设你已经按前一步设置好了目录与文件,我们来从文件系统加载一个模板文件,进行显示:

在根目录建立子目录“templates”用以存放模板文件,在其中建立文本文件“index.html.twig”,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>twig</title>
</head>
<body>
hello world ! {{name}}
</body>
</html>

在网站根目录重新建立index.php,内容如下:

<?php
require_once 'lib/Twig/Autoloader.php';
Twig_Autoloader::register();

$loader = new Twig_Loader_Filesystem('templates');
$twig = new Twig_Environment($loader, array(
    'cache' => 'templates_cache',
));
echo $twig->render('index.html.twig', array('name' => 'yunke'));


然后访问站点http://www.twigtest.com/index.php,你将会看到:

hello world ! yunke

同时在站点根目录下多出了一个子目录:

templates_cache

其中存放着为提高性能编译为php文件的模板文件,默认只编译一次,如原文件发生变化需重新编译(删除缓存)

在以上代码中Twig_Environment是twig的中枢对象,类接收两个参数:

\Twig_Environment::__construct (Twig_LoaderInterface $loader = null, $options = array())

$loader是实现了\Twig_LoaderInterface接口的加载器,用于加载模板文件

$options是选项数组,控制twig行为,有效选项如下:

debug:
是否处于调试模式,布尔值,默认为false

charset:
模板使用的字符编码,默认为 UTF-8

base_template_class:
基础模板类,用于被编译后的模板php文件,默认为Twig_Template

cache:
可选值有储存编译后模板的目录,或者为false以禁用编译缓存,这是默认值,也可以是缓存对象(接口:Twig_CacheInterface的实例,见开发者篇)

auto_reload:
布尔值,在原模板文件改变时是否重新加载,如果没有提供那么将根据debug选项决定

strict_variables:
是否使用严格变量模式,默认为false,为真时模板中使用无效变量将抛出错误,否则为NULL

autoescape:
是否全局自动转义,可能的值有:false(禁止转义),true(默认值,等效为html),html(转义html实体),js(转义js),css(转义css),url(转义url),html_attr(转义html和属性),name(基于模板扩展名设置自动转义策略),PHP callback(由一个php回调来返回转义策略,该回调接收模板的名字做参数)

optimizations:
模板编译时的优化选项,“-1”代表开启全部优化(默认值),“0”代表禁用优化,还有其他值详见下集中优化扩展一节

渲染代码:$twig->render('index.html.twig', array('name' => 'yunke'));原型为:

render($name, array $context = array())

第一个参数是模板的文件名,用于加载模板

第二个是传递给模板的变量数组,键名为在模板中的变量名,键值为对应的变量值,该变量数组称为模板的“上下文”,在模板中通过“_context”能访问到该数组,下文将多次提到“上下文”就是指该变量数组

模板文件命名:

twig模板是一个段文本内容,可以存放在数据库、php变量、文件等地方,如果是文本文件,命名是任意的,任意扩展名均可,但通常使用“.twig”或“.html.twig”作为扩展名


----上集部分(设计师篇)----

默认界定符:

{% ... %} 执行标签,用于执行语句,如控制结构
{{ ... }} 打印标签,用于打印表达式的计算结果
{# ... #} 注释标签,用于注释,类似程序中的注释:/* ..*/
#{…} 插值标签,用于向表达式中的字符串插入变量值

这些定界符只是twig的默认值,是可以完全自定义的,详见下集开发者篇

字面量Literals

字符串:如"Hello World",可用“\”转义特殊字符,如'It\'s good','c:\\Program Files'

数字:包括整数和浮点数,如4/3.14

数组:如["foo", "bar"],和php不同,不存在键名,她是一个简单的数字索引数组,可嵌套。如:

{% set a = ["one", ["two", "three"]] %}

要想输出“three”可这样访问:{{ a[1][1] }},注意采用点号语法时不能这样:{{ a.1.1 }},而要这样:{{ (a.1).1 }},这有点违反直觉

哈希表:等效于php的关联数组,如:{% set a = { 'foo': 'vfoo', 'bar': 'vbar' } %},键值可以是字面量、变量或表达式,其中键名也可以不用引号,不要引号时,并不等于键名采用了一个变量,这有点违反直觉,请看代码:

{% set foo = "yunke" %}
{% set a = { foo: 'vfoo', 'bar': 'vbar' } %}
{{ a.yunke }}

这将不会有任何输出,foo并不被认为是变量,而是字面量,要想输出'vfoo'应该使用{{ a.foo }},如果要想将foo当做变量看待,那么需要为其加上括号,如下:

{% set foo = "yunke" %}
{% set a = { (foo): 'vfoo', 'bar': 'vbar' } %}
{{ a.yunke }}

此时就可以输出'vfoo'了, 加括号实际是采用了表达式键名,此时还可以这样:
 

{% set foo = 'foo' %}
{ (foo): 'foo', (1 + 1): 'bar', (foo ~ 'b'): 'baz' }

数组和哈希表可以混合使用,且可以嵌套

布尔值:true / false,没有引号

空值:null,代表值不存在,它有个别名:none

访问变量内容:

{{yunke}} 

直接显示变量“yunke”的内容,界定符内可以有空格,如{{  yunke  }} ,下同

{{yunke.name}} 

用点号可以访问对象的属性或数组的元素,这里“yunke”可以是对象也可以是数组,name是属性名或数组键名

{{yunke[‘name’]}} 

也可以用下标,但不能用于对象,此时“yunke”只能是数组

{{ attribute(foo, 'data-bar') }}

如果属性名中包含特殊字符时可以使用属性函数,如“-”可能和减号混淆,属性函数可明确语义

如果变量不存在,将得到一个NULL值(在显示上什么也没有),如果选项中“strict_variables”值为真,那么将抛出错误,在内部点号“.”方式实际是执行以下逻辑,以foo.bar为列:

1、检查foo是否是一个数组且bar是其的有效键名,如果是则返回,否则继续

2、检查foo是否是一个对象,bar为其的一个属性,如果是则返回,否则继续

3、如果foo是一个对象,检查bar是否为一个有效的方法,是则调用,否则继续

4、如果foo是一个对象,检查是否存在getBar方法存在,是则调用,否则继续

5、如果foo是一个对象,检查是否存在isBar方法存在,是则调用,否则继续

6、如果都不满足,最后返回NULL值

而foo['bar']只适用于数组,只进行两步检查:

1、检查foo是否是一个数组且bar是其的有效键名,如果是则返回,否则继续

2、返回NULL值

所以主题开发者可以优先使用点号方式,注意foo.bar中bar可以是数字,代表数组的数字索引,如果此时使用中括号方式,数字加不加引号都没有关系

如果想访问一个变量的动态属性,可以使用attribute函数代替,见后

{{ "字面量" }}  {{ "{{}}" }}

可以通过这种方式直接输出字面量

全局变量:

是指在模板中总是有效的全局变量,默认有如下:

_self:引用到当前模板,值为不带路径的模板文件名

_context:引用到当前上下文,也就是$twig->render()的第二个参数,她总是数组

_charset:引用到当前模板的字符集,值如“UTF-8”

开发者可以通过扩展提供更多全局变量,见开发者篇

设置变量:

模板开发者可以在模板中创建变量,使用“set”:

{% set foo = 'foo' %}
{% set foo = [1, 2] %}
{% set foo = {'foo': 'bar'} %}

操作符:

操作符优先级由低到高依次为(以“,”分隔):

b-and, b-xor, b-or, or, and, ==, !=, <, >, >=, <=, in, matches, starts with, ends with, .., +, -, ~, *, /, //, %, is, **, |, [], .

点号操作符优先级最高,所有操作符如下:

数学运算符:

在模板中可以使用算术运算符号:

+(加),-(减),*(乘),/(除),%(求余),

//(相除后向下取整,舍去法取整,如20//7结果为2,-20//7为3),

**(幂运算,2**3等于8,2的3次方)

 

逻辑运算符:

and(与),or(或),not(非)

按位与、或、异或:b-and, b-or, b-xor

逻辑运算符是大小写敏感的,必须全小写

 

比较运算符:

可用常规运算符如:==, !=, <, >, >=, <=

注意没有“===”、“<>”,额外的运算符有:starts with、ends with

{% if 'Fabien' starts with 'F' %}
{% endif %}
{% if 'Fabien' ends with 'n' %}
{% endif %}

他们检查是否以字符串开始或结束,是大小写敏感的

更加复杂的比较运算符可用使用正则表达式:matches,示例如下:

{% if phone matches '/^[\\d\\.]+$/' %}
{% endif %}

注意正则表达式中有“\”时,需要双转义

 

包含操作符:

使用“in”或“not in”以测试是否被包含:

{{ 1 in [1, 2, 3] }}
{{ 'cd' in 'abcde' }}
{% if 1 not in [1, 2, 3] %} 等价于:{% if not (1 in [1, 2, 3]) %}

 

测试操作符:

在twig中设置了一些测试表达式,可用“is”、“is not”操作符进行测试:

{{ num is odd }}

这测试一个数是否为奇数,更多测试表达式如下:

constant、defined、divisibleby、empty、even、iterable、null、odd、sameas

见:https://twig.symfony.com/doc/1.x/

 

其他操作符:

“|”:管道符,用于应用一个过滤器

“..”:双点号,用于创建一个数组

如在{% set a= 1..50 %}中a将是元素从1开始50结束的数组,等效于{{ range(1, 50) }}

“~”:连接符,完全等同于php的点号“.”,用于将操作数转化为字符并连接再一起

“?:”:三元操作符,与php等效,从 Twig 1.12.0开始,以下用法是等效的:

{{ foo ?: 'no' }} 和 {{ foo ? foo : 'no' }} 相同

{{ foo ? 'yes' }} 和 {{ foo ? 'yes' : '' }} 相同

“??”:假设{{ foo ?? 'no' }},如果foo被定义了且不为null那么就返回foo的值,否则返回“no”

 

表达式插入字符串中:

可以通过“#{ }”向双引号内的字符串中插入表达式的值(单引号无效;必须是表达式,单独用于模板无效):

{{ "foo #{bar} baz" }}

{{ "foo #{1 + 2} baz" }}

 

空格控制:

默认情况下,标签后的第一个换行符被删除,但随后的换行、制表tab、空格等空白不会被修改,可以使用“spaceless”标签去移除一段内容的所有空白:

{% spaceless %}
    <div>
        <strong>foo bar</strong>
    </div>
{% endspaceless %}

这将输出:

<div><strong>foo bar</strong></div>

也可以在标签内使用减号来删除围绕标签的前或后空白:

{{- value -}}

此时减号被重载为空白修饰符,不必成对使用

过滤器:

过滤器用于对变量进行修改,使用管道符号“|”分隔,可以使用链式写法,前面的输出是后面的输入,如对变量name去除html标签,并采用标题格式(每个单词首字母大写):

{{ name|striptags|title }}

过滤器可以带参数,如将数组元素连接起来:

{{ list|join(', ') }}

也可以对整段内容使用过滤器,如将一句话大写:

{% filter upper %}

    This text becomes uppercase

{% endfilter %}

twig默认提供的过滤器请见:\Twig_Extension_Core::getFilters

或官方文档:https://twig.symfony.com/doc/1.x/

开发者可以通过扩展提供更多过滤器

字符转义:

有些变量中的内容会影响html标签,比如尖括号、单双引号、和号&等等,那么就需要转义,有两种处理办法(可混用):

1、使用选项参数autoescape自动转义全部模板变量,见前文介绍,默认是开启的,转义策略是html

2、将autoescape设置为false关闭全局变量自动转义,此时模板开发者需要对不信任的变量手动转义,操作如下:

{{ yunke.risk|e }}

形式上这和使用过滤器是一样的,“e”是“escape”的缩写,默认是使用“html”转义,需要指定其他策略请:

{{ yunke.risk|e('js') }}

可用的策略参数有:js、css、html、url、html_attr

除对单个变量转义和全局转义外,还可以对模板里一段内容中的全部变量转义(局部转义):

{% autoescape 'js' %}
    只要在这个标签内部的任何变量都会转义,注意是变量,也就是{{}}里的内容,模板内容不会转义
{% endautoescape %}

省略参数则默认使用html转义,开启局部或全局变量转义时,需要输出不转义内容要使用如下方式:

{{ var|raw }}

不管全局转义如何设置,autoescape标签将改变局部的转义模式,如下:

{% autoescape 'html' %}
    {{ var }}   {#不论全局转义如何设置 var只进行html转义 #}
    {{ var|raw }}      {# var 不转义#}
    {{ var|escape }}   {# var 只转义一次 不会双转义 #}
{% endautoescape %}

注意:标签autoescape不会影响到其内部使用included包含进来的模板

开启全局或局部转义后有如下规则需要注意:

不对字面量转义:

{{ "Twig<br />" }} {# 不转义 #}
{% set text = "Twig<br />" %}
{{ text }} {# 将转义#}

表达式结果:

{{ foo ? "Twig<br />" : "<br />Twig" }} {# 不转义 #}

{% set text = "Twig<br />" %}
{{ foo ? text : "<br />Twig" }} {#不论foo为真或假 都会转义结果#}

{% set text = "Twig<br />" %}
{{ foo ? text|raw : "<br />Twig" }} {#不论foo为真或假 都会转义结果 #}

{% set text = "Twig<br />" %}
{{ foo ? text|escape : "<br />Twig" }} {# 当转义策略和外部策略相同时不会再次转义#}

过滤器顺序:

转义被用在过滤器后,输出前,如:

{{ var|upper }} 等价于 {{ var|upper|escape }}

过滤器“raw”应该被用在最后:

{{ var|raw|upper }} {# 将转义 #}

{{ var|upper|raw }} {# 不转义#}

如果最后一个过滤器和当前转义策略相同,那么不会被再次运用:

{% autoescape 'js' %}
    {{ var|escape('html') }} {# 将再次对结果运用js转义 #}
    {{ var }} {# 只运用js转义 #}
    {{ var|escape('js') }} {# 不会再次转义 #}
{% endautoescape %}

变量转义有局限性,假设在全局转义为js时,以下代码的结果不是你想象的样子:

{{ yunke.risk|raw ~ yunke.risk }}

她看起来是原文本加js转义后的结果,但实际上全部是js转义的结果,和没有加“raw”过滤器时效果一样,所以我们在设计模板时应当尽量避免复杂的转义并充分测试,

函数:

可以像php一样使用函数,如:

{% for i in range(0, 3) %}
    {{ i }},
{% endfor %}

从Twig 1.12开始调用函数时,可不按照参数顺序赋值,可以指定函数原型中的参数名,如:

{% for i in range(low=1, high=10, step=2) %}
    {{ i }},
{% endfor %}

这样使得语义更加明确,可以忽略参数顺序,仅为部分参数赋值,其他参数使用默认值,也可以顺序方式和指定参数名方式混用,但顺序方式传递的参数必须在指定名字的参数前面,如:

{{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}

函数的参数名可在官方手册对应函数介绍的参数一节看到:

https://twig.symfony.com/doc/1.x/

开发者可以通过扩展提供更多函数

 

控制结构:

用于条件判断、循环遍历等,控制结构位于{% ... %}中:

遍历结构:

<ul>
    {% for user in users %}
        <li>{{ user.username|e }}</li>
    {% endfor %}
</ul>

没有遍历内容时可以显示默认值:

{% for user in users %}
    *<li>{{ user.username|e }}</li>
{% else %}
    No users have been found.
{% endfor %}

遍历变量键名:

<h1>Members</h1>
<ul>
    {% for key in users|keys %}
        <li>{{ key }}</li>
    {% endfor %}
</ul>

遍历键和值:

<h1>Members</h1>
<ul>
    {% for key, user in users %}
        <li>{{ key }}: {{ user.username|e }}</li>
    {% endfor %}
</ul>

添加条件遍历,仅遍历条件为真的条目:

<ul>
    {% for user in users if user.active %}
        <li>{{ user.username|e }}</li>
    {% endfor %}
</ul>

遍历部分内容:

<h1>Top Ten Members</h1>
<ul>
    {% for user in users|slice(0, 10) %}
        <li>{{ user.username|e }}</li>
    {% endfor %}
</ul>

在for结构中可以使用特殊变量loop,如:

loop.index:当前迭代了第几次,从1开始
loop.index0:当前迭代了第几次,从0开始
loop.revindex:剩余迭代次数,最后是1
loop.revindex0:剩余迭代次数,最后是0
loop.first:是否为第一次迭代
loop.last:是否为最后一次迭代
loop.length:迭代的条目总数
loop.parent:引用到外层循环上下文

在指定循环条件时,loop变量是无效的

注意在for中没有break 或者 continue结构,遍历可以针对数组或者是实现了迭代器接口的对象

条件判断:

{% if users|length > 0 %}
show user
{% endif %}

也可以测试是否为空:

{% if users %}
    <ul>
        {% for user in users %}
            <li>{{ user.username|e }}</li>
        {% endfor %}
    </ul>
{% endif %}

取反:

{% if not user.subscribed %}
    <p>You are not subscribed to our mailing list.</p>
{% endif %}

也可以多分枝条件判断:

{% if 3 > yunke|length > 0 %}
    show 0-3
{% elseif 5 > yunke|length >= 3 %}
    show 3-5
{% else %}
    show 5-..
{% endif %}

是否为true规则和php一样:

空字符串:false
数字0:	false
字符串:true
非零数字:true
空白字符串:true
字符串“0”:false
空数组:false
NULL:false
非空数组:true
对象:true

作用域控制:

使用with标签可以创建一个新的作用域,里面的变量仅在内部有效,标签外部无效,示例如下:

{% with %}
    {% set foo = 42 %}
    {{ foo }}           foo is 42 here
{% endwith %}

变量foo在该标签以外是访问不到的,以上列子还可以换一种方式书写:

{% with { foo: 42 } %}
    {{ foo }}           foo is 42 here
{% endwith %}

也就是将变量集中到哈希中传入;默认情况下新建的作用域内可以访问外部变量,可以使用以下方式禁止:

{% set bar = 'bar' %}
{% with { foo: 42 } only %}
    {# only foo is defined #}
    {# bar is not defined #}
{% endwith %}

和普通编程语言相比没有while(){}、do{}while()等结构,但twig的强大之处就是可以通过添加扩展的方式让她有,不过默认是没有的

 

加载其他模板:

在一个模板中可以通过如下方式加载其他模板:

{% include('sidebar.html') %}

也可以使用变量,如:

{% include var ~ '_foo.html' %}

实际上include关键词后可以是任意表达式,更复杂的如:

{% include var|default('index') ~ '_foo.html' %}

通过这种方式包含其他模板后,在include语句位置能使用的有效变量,在被加载的模板中也有效,如下:

{% for box in boxes %}
    {{ include('render_box.html') }}
{% endfor %}

在render_box.html中可以使用变量box,被加载的模板名依赖于加载器的类型,如果是文件系统加载器,那么可以使用路径名。

模板继承:

一个模板可以把一个区域定义成块,这样其他模板可以声明继承该模板,声明后就成了该模板的子模板,相对的该模板就是父模板,子模板可以通过块名覆写父模板中定义的块,如果不覆写将使用父模板的内容,这称为模板继承,父模板声明块和子模板覆写块都使用如下方式:

{% block blockName %}…{% endblock %}

在子模板中声明继承需在第一行使用如下语句:

{% extends "base.html" %}

这里extends可以使用表达式以加载不同模板,如:

{% extends request.ajax ? "base_ajax.html" : "base.html" %}

模板继承示例如下,比如a.html.twig是父模板,内容如下:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>twig</title>
</head>
<body>
{% block yunke %}
    <div>我是父模板a.html.twig中的内容</div>
{% endblock %}
</body>
</html>

b.html.twig是子模板,内容如下:

{% extends "a.html.twig" %}
{% block yunke %}
    <div>我是子模板b.html.twig中的内容</div>
{{ parent() }}
{% endblock %}

使用echo $twig->render('b.html.twig');将输出:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>twig</title>
</head>
<body>
    <div>我是子模板b.html.twig中的内容</div>
    <div>我是父模板a.html.twig中的内容</div>

</body>
</html>

如你所见{{ parent() }}用于输出父模板中的块内容

不管是子模板还是父模板,他们共享相同的上下文变量

需要注意如果B继承了A,也就是说B是A的子模板,那么在输出时B里面只能对A的块进行覆写,不能输出块外的内容,但b里面可进行变量赋值等非输出操作,在b里的逻辑先于a执行,因此在b中对变量或上下文的赋值将应用在a中

宏命令Macros

当有些模板内容会被反复多次用到时,可以将其定义为宏,在使用的地方进行宏调用即可,里面需要用到的变量可以通过宏参数传入,这有点像编程语言中定义函数,新建一个模板,在里面定义宏(如同在函数库文件中定义函数),假设模板名为macrod.html.twig,内容如下:

{% macro input(name, value = "", type = "text", size = 20) %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
{% endmacro %}

{% macro user(name="匿名用户", tel = "未知") %}
用户名:{{ name }}  电话号码:{{ tel }}
{% endmacro %}

这就在一个文件中声明了两个宏,在其他模板中需要用到时,可以这样:

{% import "macrod.html.twig" as lib %}
<p>{{ lib.input('username') }}</p>
<p>{{ lib.user('yunke',"13812345678") }}</p>
<p>{{ lib.user() }}</p>

这将输出:

<p>    <input type="text" name="username" value="" size="20" />
</p>
<p>用户名:yunke  电话号码:13812345678
</p>
<p>用户名:匿名用户  电话号码:未知
</p>

导入语句{% import "macrod.html.twig" as lib %}只需要放在宏调用前即可,上列是将整个文件引用进来然后给了一个别名“lib”,你也可以只导入某具体的宏,输出效果是一样的,如下:

{% from 'macrod.html.twig' import user as id %}
<p>{{ id('yunke',"13812345678") }}</p>

在上面的列子中,如果在macrod.html.twig中出现任何宏声明之外的内容,将会被忽略,不会引起错误,我们应该认识到宏模板文件应该只用来定义宏

如果在进行宏调用时传递了多于的参数,那么多于的参数将以列表方式储存在特殊变量varargs中,在宏内可以使用for结构去遍历她,如下:

{% macro user(name="匿名用户", tel = "未知") %}
用户名:{{ name }}  电话号码:{{ tel }}  {% for arg in varargs  %}额外参数:{{ arg }}{% endfor %}
{% endmacro %}

此时如果没有传递多于参数,将不会有额外部分的显示,换句话说varargs不包含有声明的参数

在宏声明时最佳实践是在参数上定义默认值,否则在宏内使用该参数时应当给出默认值

 

模板编码标准:

在编写模板代码时推荐遵从官方的标准编码风格,这不是强制的,但这样有较好的可读性,也叫做官方推荐最佳实践,简要如下:

1、在开始定界符后和结束定界符前,有且仅有一个空格

2、当使用空白控制符“-”时,不要在她和定界符之间放置任何空白

3、在操作符前后各使用一个空格,有且仅有一个

4、在数组的“,”和哈希表的“:”之后有且仅有一个空格

5、在开始圆括号后、结束圆括号前不要放置任何空白

6、在引号前后不要放置空白

7、在操作符|, ., .., []前后不要放置空白

8、过滤器和函数的圆括号前后不要空白

9、使用小写变量名,单词间用下划线

10、对齐标签,统一缩进

官网最佳实践网址为:

https://twig.symfony.com/doc/1.x/coding_standards.html

 

补充:

1、模板开发者可以在这里在线测试自己的模板:

https://twigfiddle.com

可以通过多种格式(yaml、json、xml、ini)传递变量,然后显示

2、twig模板引擎是高度可扩展的,开发者可以通过扩展提供更多全局变量、过滤器、函数、操作符、控制结构等等,请见开发者篇

 

我是云客,【云游天下,做客四方】,微信号:php-world,欢迎转载,但须注明出处,讨论请加qq群203286137

 

 

 

猜你喜欢

转载自blog.csdn.net/u011474028/article/details/81086725