Twig 是个 简单而强力的模板,因为在学习sf 所以看看她。
第一章
目前支持的tags包括
for if macro filter set extends block include import from use spaceless autoescape raw flush do
twig在html分为3种
{{...}} 直接输出其中的变量
{#...#} 注释标签
{%...%} 命令标签,就是我们要学习的这些
for标签
这个最简单,就是循环。
基于数组的循环
- <h1>Members</h1>
- <ul>
- {% for user in users %}
- <li>{{ user.username|e }}</li>
- {% endfor %}
- </ul>
基于数字的循环,特别要注意,这里会输出0-10 也就是11个数字。
- {% for i in 0..10 %}
- * {{ i }}
- {% endfor %}
基于字母的循环
- {% for letter in 'a'..'z' %}
- * {{ letter }}
- {% endfor %}
变量名 | 描述 |
---|---|
loop.index | 循环的次数(从1开始) |
loop.index0 | 循环的次数(从0开始) |
loop.revindex | 循环剩余次数(最小值为1) |
loop.revindex0 | 循环剩余次数(最小值为0) |
loop.first | 当第一次循环的时候返回true |
loop.last | 当最后一次循环的时候返回true |
loop.length | 循环的总数 |
loop.parent | 被循环的数组 |
loop.length, loop.revindex, loop.revindex0,loop.last 这几个值只有在被循环的是 php数组 或实现了Countable 接口的类,才有效。
添加一个条件
跟PHP不一样,在循环内部不支持break和continue语句,你只能通过过滤器去跳过一些循环,就像这样
- <ul>
- {% for user in users if user.active %}
- <li>{{ user.username|e }}</li>
- {% endfor %}
- </ul>
else 分支
如果 users是个空数组就会输出no user found 。
- <ul>
- {% for user in users %}
- <li>{{ user.username}}</li>
- {% else %}
- <li><em>no user found</em></li>
- {% endfor %}
- </ul>
按keys循环
- <h1>Members</h1>
- <ul>
- {% for key in users|keys %}
- <li>{{ key }}</li>
- {% endfor %}
- </ul>
按keys, values循环
- <h1>Members</h1>
- <ul>
- {% for key, user in users %}
- <li>{{ key }}: {{ user.username|e }}</li>
- {% endfor %}
- </ul>
if标签
- {% if users %}
- <ul>
- {% for user in users %}
- <li>{{ user.username|e }}</li>
- {% endfor %}
- </ul>
- {% endif %}
- {% if kenny.sick %}
- Kenny is sick.
- {% elseif kenny.dead %}
- You killed Kenny! You bastard!!!
- {% else %}
- Kenny looks okay --- so far
- {% endif %}
macro标签
macro(宏标签)类似于其他语言中的函数,常用于填充html标签,以下是一个例子,用来渲染<input>
- {% macro input(name, value, type, size) %}
- <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
- {% endmacro %}
1、参数的默认值是通过macro块内部的 default过滤器来定义的。
2、参数总是可选的。
另外,就跟php函数一样,macro内部是无法使用外部的变量的。但你可以传递一个特殊变量_context作为参数来获取整个内容。
macro可以被定义在任何的模板内,但在你使用之前需要使用 imported
- {% import "forms.html" as forms %}
- <p>{{ forms.input('username') }}</p>
- <p>{{ forms.input('password', null, 'password') }}</p>
如果你要在定义macro的模板里使用,就不需要imported 可以使用特殊变量_self
- <p>{{ _self.input('username') }}</p>
如果你要定义一个macro里 包含另一个macro,并且两个macro在同一个文件里,可以使用特殊变量_self
- {% macro input(name, value, type, size) %}
- <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
- {% endmacro %}
- {% macro wrapped_input(name, value, type, size) %}
- <div class="field">
- {{ _self.input(name, value, type, size) }}
- </div>
- {% endmacro %}
- {# forms.html #}
- {% macro input(name, value, type, size) %}
- <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
- {% endmacro %}
- {# shortcuts.html #}
- {% macro wrapped_input(name, value, type, size) %}
- {% import "forms.html" as forms %}
- <div class="field">
- {{ forms.input(name, value, type, size) }}
- </div>
- {% endmacro %}
filter标签
就是给整个区块使用过滤器
- {% filter upper %}
- This text becomes uppercase
- {% endfilter %}
- {% filter lower|escape %}
- <strong>SOME TEXT</strong>
- {% endfilter %}
第二章
set标签
主要是用来给变量赋值的。
- {% set foo = 'foo' %}
- {% set foo = [1, 2] %}
- {% set foo = {'foo': 'bar'} %}
- {% set foo = 'foo' ~ 'bar' %}
- {% set foo, bar = 'foo', 'bar' %}
其中 'foo'~'bar' 这个我没怎么看明白,测试了一下,可能是字符串连接的。
set还有一种用法,就是把 块内的内容赋值给变量
- {% set foo %}
- <div id="pagination">
- ...
- </div>
- {% endset %}
extends标签
这个标签用来表示本模板继承自另外一个模板。和php一样,twig不支持多重继承,所以你只能有一个extends标签,而且要在模板的最上方。
我们先来定义一个“基模板” base.html 他就像一个骨架一个。
- <!DOCTYPE html>
- <html>
- <head>
- {% block head %}
- <link rel="stylesheet" href="style.css" />
- <title>{% block title %}{% endblock %} - My Webpage</title>
- {% endblock %}
- </head>
- <body>
- <div id="content">{% block content %}{% endblock %}</div>
- <div id="footer">
- {% block footer %}
- © Copyright 2011 by <a href="http://domain.invalid/">you</a>.
- {% endblock %}
- </div>
- </body>
- </html>
{% block %}标签定义了4个区块(block head, block title, block content, block footer),可以让子模板来填充内容。block的作用就是告诉模板引擎,这里面的内容可以被子模板覆盖。
一个子模板大概类似于这样的
- {% extends "base.html" %}
- {% block title %}Index{% endblock %}
- {% block head %}
- {{ parent() }}
- <style type="text/css">
- .important { color: #336699; }
- </style>
- {% endblock %}
- {% block content %}
- <h1>Index</h1>
- <p class="important">
- Welcome on my awesome homepage.
- </p>
- {% endblock %}
extends是非常关键的,它告诉模板引擎,本模板继承自另一个模板(base.html)。当模板引擎解析到本模板时,会首先载入父模板。extends标签应该是模板内的第一个标签。
如果子模板没有定义block footer ,那么父模板会用默认值代替。
注意:block标签的名字是不能重复的。如果你想让同一个block多次打印。可以使用block函数
- <title>{% block title %}{% endblock %}</title>
- <h1>{{ block('title') }}</h1>
- {% block body %}{% endblock %}
父block
也许你会需要 父block的内容。可以使用parent函数,这很有用比如你想往一个block里添加内容而不是覆盖时。
- {% block sidebar %}
- <h3>Table Of Contents</h3>
- ...
- {{ parent() }}
- {% endblock %}
命名endblock
模板引擎 允许你命名结束标记,这样可读性会提高很多。但个人觉得没啥用处。
- {% block sidebar %}
- {% block inner_sidebar %}
- ...
- {% endblock inner_sidebar %}
- {% endblock sidebar %}
嵌套block
允许你嵌套生成block ,来形成更复杂的block
- {% for item in seq %}
- <li>{% block loop_item %}{{ item }}{% endblock %}</li>
- {% endfor %}
简写block
以下这两种写法是等效的
- {% block title %}
- {{ page_title|title }}
- {% endblock %}
- {% block title page_title|title %}
动态继承
你可以用一个变量来继承不同的模板。
- {% extends some_var %}
如果变量是一个twig模板对象,也可以。
- $layout = $twig->loadTemplate('some_layout_template.twig');
- $twig->display('template.twig', array('layout' => $layout));
1.2版本更新 你可以传递一个数组,twig会选择第一个存在的模板,来继承。
- {% extends ['layout.html', 'base_layout.html'] %}
条件继承
这个很简单自己看吧,
- {% extends standalone ? "minimum.html" : "base.html" %}
block标签
参见 extends标签
include标签
载入一个模板,返回渲染的内容。载入的模板可以使用当前模板的变量
- {% include 'header.html' %}
- Body
- {% include 'footer.html' %}
你可以给模板添加变量
- {# the foo template will have access to the variables from the current context and the foo one #}
- {% include 'foo' with {'foo': 'bar'} %}
- {% set vars = {'foo': 'bar'} %}
- {% include 'foo' with vars %}
你也可以使用 only 关键字 来禁止载入的模板使用当前模板的变量,只能使用include 时with的变量
- {# only the foo variable will be accessible #}
- {% include 'foo' with {'foo': 'bar'} only %}
- {# no variable will be accessible #}
- {% include 'foo' only %}
载入的模板名也可以是一个twig表达式
- {% include some_var %}
- {% include ajax ? 'ajax.html' : 'not_ajax.html' %}
也可以用twig模板对象
- $template = $twig->loadTemplate('some_template.twig');
- $twig->loadTemplate('template.twig')->display(array('template' => $template));
1.2版本新加内容,可以在模板加上 ignore missing 关键字,这样当模板不存在的时候就不会引发错误。
- {% include "sidebar.html" ignore missing %}
- {% include "sidebar.html" ignore missing with {'foo': 'bar} %}
- {% include "sidebar.html" ignore missing only %}
1.2版本新加内容,你可以给include传递一个数组,他会自动载入第一个存在的模板
- {% include ['page_detailed.html', 'page.html'] %}
import 标签
twig允许把一些常用的代码放入到macros(宏)里,这些macros被不同的模板导入。
有两种方法导入模板,你可以导入整个模板到一个变量里,或者只导入需要的几个macros
假如我们有个助手模块,来帮助我们渲染表单(forms.html)
- {% macro input(name, value, type, size) %}
- <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
- {% endmacro %}
- {% macro textarea(name, value, rows) %}
- <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>
- {% endmacro %}
最简单,最灵活的办法就是导入整个模板。(把模板导入到 forms变量里)
- {% import 'forms.html' as forms %}
- <dl>
- <dt>Username</dt>
- <dd>{{ forms.input('username') }}</dd>
- <dt>Password</dt>
- <dd>{{ forms.input('password', null, 'password') }}</dd>
- </dl>
- <p>{{ forms.textarea('comment') }}</p>
或者你可以导入模板的名字到当前的名字空间下。 (导入input,textarea 并把input重名为input_field)
- {% from 'forms.html' import input as input_field, textarea %}
- <dl>
- <dt>Username</dt>
- <dd>{{ input_field('username') }}</dd>
- <dt>Password</dt>
- <dd>{{ input_field('password', '', 'password') }}</dd>
- </dl>
- <p>{{ textarea('comment') }}</p>
如果是当前模板内定义的macros,那就不必导入了,直接使用特殊变量_self
- {# index.html template #}
- {% macro textarea(name, value, rows) %}
- <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>
- {% endmacro %}
- <p>{{ _self.textarea('comment') }}</p>
那么你仍然可以导入_self到一个变量里,尽管这看起来很。。。没用。。
- {# index.html template #}
- {% macro textarea(name, value, rows) %}
- <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>
- {% endmacro %}
- {% import _self as forms %}
- <p>{{ forms.textarea('comment') }}</p>
第三章
from标签
参见 import标签
use标签
- {% extends "base.html" %}
- {% use "blocks.html" %}
- {% block title %}{% endblock %}
- {% block content %}{% endblock %}
- # blocks.html
- {% block sidebar %}{% endblock %}
运行的结果几乎等于
- {% extends "base.html" %}
- {% block sidebar %}{% endblock %}
- {% block title %}{% endblock %}
- {% block content %}{% endblock %}
要注意,被use标签导入的模板(上例中的block.html),不能再继承别的模板,不能定义宏macros。但它可以再use其他模板。
- {% extends "base.html" %}
- {% use "blocks.html" with sidebar as base_sidebar %}
- {% block sidebar %}{% endblock %}
- {% block title %}{% endblock %}
- {% block content %}{% endblock %}
1.3版本新支持了 parent()函数,(这个特别重要)
- {% extends "base.html" %}
- {% use "blocks.html" %}
- {% block sidebar %}
- {{ parent() }}
- {% endblock %}
- {% block title %}{% endblock %}
- {% block content %}{% endblock %}
注意,parent()的内容 其实是blocks.html里的block sidebar的内容。因为继承树是 base.html->blocks.html->本模板
- {% extends "base.html" %}
- {% use "blocks.html" with sidebar as parent_sidebar %}
- {% block sidebar %}
- {{ block('parent_sidebar') }}
- {% endblock %}
你可以使用任意数量的use标签,如果多个use标签里的block名字存在重复,那么最后use的那个有效。
spacelsee标签
- {% spaceless %}
- <div>
- <strong>foo</strong>
- </div>
- {% endspaceless %}
- {# output will be <div><strong>foo</strong></div> #}
autoescape标签
- {% autoescape true %}
- Everything will be automatically escaped in this block
- {% endautoescape %}
- {% autoescape false %}
- Everything will be outputed as is in this block
- {% endautoescape %}
- {% autoescape true js %}
- Everything will be automatically escaped in this block
- using the js escaping strategy
- {% endautoescape %}
而我这么测试。输出的还是原本的内容。
- {% autoescape true %}
- <body><b>aaaa</b></body>
- {% endautoescape %}
- {% autoescape false %}
- <b>aaaa</b>
- {% endautoescape %}
- {% autoescape true js %}
- <script>
- function aaa(){alert('x');}
- </script>
- {% endautoescape %}
这个请教各位路过的师兄了。。。
- {% autoescape true %}
- {{ safe_value|raw }}
- {% endautoescape %}
- {% do 1 + 2 %}