[学习笔记] Twig 的 tags学习 [转]

Twig 是个 简单而强力的模板,因为在学习sf 所以看看她。

第一章

目前支持的tags包括

    for    if    macro    filter    set    extends    block    include    import    from    use    spaceless    autoescape    raw    flush    do

twig在html分为3种

{{...}} 直接输出其中的变量

{#...#} 注释标签

{%...%} 命令标签,就是我们要学习的这些

for标签

这个最简单,就是循环。

基于数组的循环

  1. <h1>Members</h1>  
  2. <ul>  
  3.     {% for user in users %}  
  4.         <li>{{ user.username|e }}</li>  
  5.     {% endfor %}  
  6. </ul>  


基于数字的循环,特别要注意,这里会输出0-10 也就是11个数字。

  1. {% for i in 0..10 %}  
  2.     * {{ i }}  
  3. {% endfor %}  

基于字母的循环

  1. {% for letter in 'a'..'z' %}  
  2.     * {{ letter }}  
  3. {% endfor %}  


在循环体内部的变量

变量名描述
loop.index 循环的次数(从1开始)
loop.index0 循环的次数(从0开始)
loop.revindex 循环剩余次数(最小值为1)
loop.revindex0 循环剩余次数(最小值为0)
loop.first 当第一次循环的时候返回true
loop.last 当最后一次循环的时候返回true
loop.length 循环的总数
loop.parent 被循环的数组

loop.lengthloop.revindexloop.revindex0,loop.last 这几个值只有在被循环的是 php数组 或实现了Countable 接口的类,才有效。

添加一个条件

跟PHP不一样,在循环内部不支持break和continue语句,你只能通过过滤器去跳过一些循环,就像这样

  1. <ul>  
  2.     {% for user in users if user.active %}  
  3.         <li>{{ user.username|e }}</li>  
  4.     {% endfor %}  
  5. </ul>  


else 分支

如果 users是个空数组就会输出no user found 。

  1. <ul>  
  2.     {% for user in users %}  
  3.         <li>{{ user.username}}</li>  
  4.     {% else %}  
  5.         <li><em>no user found</em></li>  
  6.     {% endfor %}  
  7. </ul>  

按keys循环

  1. <h1>Members</h1>  
  2. <ul>  
  3.     {% for key in users|keys %}  
  4.         <li>{{ key }}</li>  
  5.     {% endfor %}  
  6. </ul>  


按keys, values循环

  1. <h1>Members</h1>  
  2. <ul>  
  3.     {% for key, user in users %}  
  4.         <li>{{ key }}: {{ user.username|e }}</li>  
  5.     {% endfor %}  
  6. </ul>  



if标签

这个不用多说,直接看例子

  1. {% if users %}  
  2.     <ul>  
  3.         {% for user in users %}  
  4.             <li>{{ user.username|e }}</li>  
  5.         {% endfor %}  
  6.     </ul>  
  7. {% endif %}  
  8.   
  9. {% if kenny.sick %}  
  10.     Kenny is sick.  
  11. {% elseif kenny.dead %}  
  12.     You killed Kenny!  You bastard!!!  
  13. {% else %}  
  14.     Kenny looks okay --- so far  
  15. {% endif %}  


macro标签

macro(宏标签)类似于其他语言中的函数,常用于填充html标签,以下是一个例子,用来渲染<input>

  1. {% macro input(name, value, type, size) %}  
  2.     <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />  
  3. {% endmacro %}  


macro与函数的不同之处在于:

1、参数的默认值是通过macro块内部的 default过滤器来定义的。

2、参数总是可选的。

另外,就跟php函数一样,macro内部是无法使用外部的变量的。但你可以传递一个特殊变量_context作为参数来获取整个内容。

macro可以被定义在任何的模板内,但在你使用之前需要使用 imported

  1. {% import "forms.html" as forms %}  

然后就可以这样使用了

  1. <p>{{ forms.input('username') }}</p>  
  2. <p>{{ forms.input('password', null, 'password') }}</p>  

如果你要在定义macro的模板里使用,就不需要imported 可以使用特殊变量_self

  1. <p>{{ _self.input('username') }}</p>  


如果你要定义一个macro里 包含另一个macro,并且两个macro在同一个文件里,可以使用特殊变量_self

  1. {% macro input(name, value, type, size) %}  
  2.   <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />  
  3. {% endmacro %}  
  4.   
  5. {% macro wrapped_input(name, value, type, size) %}  
  6.     <div class="field">  
  7.         {{ _self.input(name, value, type, size) }}  
  8.     </div>  
  9. {% endmacro %}  


如果两个macro在不同的文件里,你需要使用import

  1. {# forms.html #}  
  2.   
  3. {% macro input(name, value, type, size) %}  
  4.   <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />  
  5. {% endmacro %}  
  6.   
  7. {# shortcuts.html #}  
  8.   
  9. {% macro wrapped_input(name, value, type, size) %}  
  10.     {% import "forms.html" as forms %}  
  11.     <div class="field">  
  12.         {{ forms.input(name, value, type, size) }}  
  13.     </div>  
  14. {% endmacro %}  


filter标签

就是给整个区块使用过滤器

  1. {% filter upper %}  
  2.     This text becomes uppercase  
  3. {% endfilter %}  


    1. {% filter lower|escape %}  
    2.     <strong>SOME TEXT</strong>  
    3. {% endfilter %}  

 

第二章

set标签

主要是用来给变量赋值的。

  1. {% set foo = 'foo' %}  
  2.   
  3. {% set foo = [1, 2] %}  
  4.   
  5. {% set foo = {'foo': 'bar'} %}  
  6.   
  7. {% set foo = 'foo' ~ 'bar' %}  
  8.   
  9. {% set foo, bar = 'foo', 'bar' %}  


其中 'foo'~'bar' 这个我没怎么看明白,测试了一下,可能是字符串连接的。

set还有一种用法,就是把 块内的内容赋值给变量

  1. {% set foo %}  
  2.   <div id="pagination">  
  3.     ...  
  4.   </div>  
  5. {% endset %}  

extends标签

这个标签用来表示本模板继承自另外一个模板。和php一样,twig不支持多重继承,所以你只能有一个extends标签,而且要在模板的最上方。

我们先来定义一个“基模板” base.html 他就像一个骨架一个。

  1. <!DOCTYPE html>  
  2. <html>  
  3.     <head>  
  4.         {% block head %}  
  5.             <link rel="stylesheet" href="style.css" />  
  6.             <title>{% block title %}{% endblock %} - My Webpage</title>  
  7.         {% endblock %}  
  8.     </head>  
  9.     <body>  
  10.         <div id="content">{% block content %}{% endblock %}</div>  
  11.         <div id="footer">  
  12.             {% block footer %}  
  13.                 © Copyright 2011 by <a href="http://domain.invalid/">you</a>.  
  14.             {% endblock %}  
  15.         </div>  
  16.     </body>  
  17. </html>  


{% block %}标签定义了4个区块(block head, block title, block content, block footer),可以让子模板来填充内容。block的作用就是告诉模板引擎,这里面的内容可以被子模板覆盖。

一个子模板大概类似于这样的

  1. {% extends "base.html" %}  
  2.   
  3. {% block title %}Index{% endblock %}  
  4. {% block head %}  
  5.     {{ parent() }}  
  6.     <style type="text/css">  
  7.         .important { color: #336699; }  
  8.     </style>  
  9. {% endblock %}  
  10. {% block content %}  
  11.     <h1>Index</h1>  
  12.     <p class="important">  
  13.         Welcome on my awesome homepage.  
  14.     </p>  
  15. {% endblock %}  


extends是非常关键的,它告诉模板引擎,本模板继承自另一个模板(base.html)。当模板引擎解析到本模板时,会首先载入父模板。extends标签应该是模板内的第一个标签。

如果子模板没有定义block footer ,那么父模板会用默认值代替。

注意:block标签的名字是不能重复的。如果你想让同一个block多次打印。可以使用block函数

  1. <title>{% block title %}{% endblock %}</title>  
  2. <h1>{{ block('title') }}</h1>  
  3. {% block body %}{% endblock %}  

父block

也许你会需要 父block的内容。可以使用parent函数,这很有用比如你想往一个block里添加内容而不是覆盖时。

  1. {% block sidebar %}  
  2.     <h3>Table Of Contents</h3>  
  3.     ...  
  4.     {{ parent() }}  
  5. {% endblock %}  

命名endblock

模板引擎 允许你命名结束标记,这样可读性会提高很多。但个人觉得没啥用处。

  1. {% block sidebar %}  
  2.     {% block inner_sidebar %}  
  3.         ...  
  4.     {% endblock inner_sidebar %}  
  5. {% endblock sidebar %}  

嵌套block

允许你嵌套生成block ,来形成更复杂的block

  1. {% for item in seq %}  
  2.     <li>{% block loop_item %}{{ item }}{% endblock %}</li>  
  3. {% endfor %}  

简写block

以下这两种写法是等效的

  1. {% block title %}  
  2.     {{ page_title|title }}  
  3. {% endblock %}  
  4.   
  5. {% block title page_title|title %}  

动态继承

你可以用一个变量来继承不同的模板。

  1. {% extends some_var %}  


如果变量是一个twig模板对象,也可以。

  1. $layout = $twig->loadTemplate('some_layout_template.twig');  
  2.   
  3. $twig->display('template.twig', array('layout' => $layout));  


1.2版本更新 你可以传递一个数组,twig会选择第一个存在的模板,来继承。

  1. {% extends ['layout.html', 'base_layout.html'] %}  

条件继承

这个很简单自己看吧,

  1. {% extends standalone ? "minimum.html" : "base.html" %}  



block标签

参见 extends标签

include标签

载入一个模板,返回渲染的内容。载入的模板可以使用当前模板的变量

  1. {% include 'header.html' %}  
  2.     Body  
  3. {% include 'footer.html' %}  

你可以给模板添加变量

  1. {# the foo template will have access to the variables from the current context and the foo one #}  
  2. {% include 'foo' with {'foo': 'bar'} %}  
  3.   
  4. {% set vars = {'foo': 'bar'} %}  
  5. {% include 'foo' with vars %}  


你也可以使用 only 关键字 来禁止载入的模板使用当前模板的变量,只能使用include 时with的变量

  1. {# only the foo variable will be accessible #}  
  2. {% include 'foo' with {'foo': 'bar'} only %}  
  3.   
  4. {# no variable will be accessible #}  
  5. {% include 'foo' only %}  

载入的模板名也可以是一个twig表达式

  1. {% include some_var %}  
  2. {% include ajax ? 'ajax.html' : 'not_ajax.html' %}  


也可以用twig模板对象

  1. $template = $twig->loadTemplate('some_template.twig');  
  2.   
  3. $twig->loadTemplate('template.twig')->display(array('template' => $template));  

1.2版本新加内容,可以在模板加上 ignore missing 关键字,这样当模板不存在的时候就不会引发错误。

  1. {% include "sidebar.html" ignore missing %}  
  2. {% include "sidebar.html" ignore missing with {'foo': 'bar} %}  
  3. {% include "sidebar.html" ignore missing only %}  

1.2版本新加内容,你可以给include传递一个数组,他会自动载入第一个存在的模板

  1. {% include ['page_detailed.html', 'page.html'] %}  

import 标签

twig允许把一些常用的代码放入到macros(宏)里,这些macros被不同的模板导入。

有两种方法导入模板,你可以导入整个模板到一个变量里,或者只导入需要的几个macros

假如我们有个助手模块,来帮助我们渲染表单(forms.html)

  1. {% macro input(name, value, type, size) %}  
  2.     <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />  
  3. {% endmacro %}  
  4.   
  5. {% macro textarea(name, value, rows) %}  
  6.     <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>  
  7. {% endmacro %}  


最简单,最灵活的办法就是导入整个模板。(把模板导入到 forms变量里)

  1. {% import 'forms.html' as forms %}  
  2.   
  3. <dl>  
  4.     <dt>Username</dt>  
  5.     <dd>{{ forms.input('username') }}</dd>  
  6.     <dt>Password</dt>  
  7.     <dd>{{ forms.input('password', null, 'password') }}</dd>  
  8. </dl>  
  9. <p>{{ forms.textarea('comment') }}</p>  


或者你可以导入模板的名字到当前的名字空间下。 (导入input,textarea 并把input重名为input_field)

  1. {% from 'forms.html' import input as input_field, textarea %}  
  2.   
  3. <dl>  
  4.     <dt>Username</dt>  
  5.     <dd>{{ input_field('username') }}</dd>  
  6.     <dt>Password</dt>  
  7.     <dd>{{ input_field('password', '', 'password') }}</dd>  
  8. </dl>  
  9. <p>{{ textarea('comment') }}</p>  

如果是当前模板内定义的macros,那就不必导入了,直接使用特殊变量_self

  1. {# index.html template #}  
  2.   
  3. {% macro textarea(name, value, rows) %}  
  4.     <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>  
  5. {% endmacro %}  
  6.   
  7. <p>{{ _self.textarea('comment') }}</p>  


那么你仍然可以导入_self到一个变量里,尽管这看起来很。。。没用。。

  1. {# index.html template #}  
  2.   
  3. {% macro textarea(name, value, rows) %}  
  4.     <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>  
  5. {% endmacro %}  
  6.   
  7. {% import _self as forms %}  
  8.   
  9. <p>{{ forms.textarea('comment') }}</p>  

第三章

from标签

参见 import标签

use标签

use标签是1.1版本新添加内容。
这个use标签主要是来解决模板只能从一个父模板继承,而你又想重用其他模板的问题。但是use标签只会导入block区块,
(注意import只会导入宏macros,include会导入一切。这三个标签要区分清楚)
比如
  1. {% extends "base.html" %}  
  2.   
  3. {% use "blocks.html" %}  
  4.   
  5. {% block title %}{% endblock %}  
  6. {% block content %}{% endblock %}  
而blocks.html的内容是
  1. # blocks.html  
  2. {% block sidebar %}{% endblock %}  
我们从blocks..html导入了 block sidebar
运行的结果几乎等于
  1. {% extends "base.html" %}  
  2.   
  3. {% block sidebar %}{% endblock %}  
  4. {% block title %}{% endblock %}  
  5. {% block content %}{% endblock %}  

要注意,被use标签导入的模板(上例中的block.html),不能再继承别的模板,不能定义宏macros。但它可以再use其他模板。
另外use标签后面的文件名,不能是一个表达式。
 
当被导入了的block和主模板的block重名了,模板引擎会自动忽略被use标签导入block。
为了避免这种情况。你可以在使用use标签的时候,给block重命名
  1. {% extends "base.html" %}  
  2.   
  3. {% use "blocks.html" with sidebar as base_sidebar %}  
  4.   
  5. {% block sidebar %}{% endblock %}  
  6. {% block title %}{% endblock %}  
  7. {% block content %}{% endblock %}  

1.3版本新支持了 parent()函数,(这个特别重要)
parent()函数,会自动的搞定block的继承树,如果你在主模板里覆盖了use标签引入进来的block块,而用parent()函数则可以调用被覆盖的那个block内容
  1. {% extends "base.html" %}  
  2.   
  3. {% use "blocks.html" %}  
  4.   
  5. {% block sidebar %}  
  6.     {{ parent() }}  
  7. {% endblock %}  
  8.   
  9. {% block title %}{% endblock %}  
  10. {% block content %}{% endblock %}  

注意,parent()的内容 其实是blocks.html里的block sidebar的内容。因为继承树是  base.html->blocks.html->本模板
 
如果你在use标签里给导入的block重命名了,那就可以使用block函数,来代替上面代码中的parent函数所达到的效果
[javascript]view plaincopyprint?
 
  1. {% extends "base.html" %}  
  2.   
  3. {% use "blocks.html" with sidebar as parent_sidebar %}  
  4.   
  5. {% block sidebar %}  
  6.     {{ block('parent_sidebar') }}  
  7. {% endblock %}  

你可以使用任意数量的use标签,如果多个use标签里的block名字存在重复,那么最后use的那个有效。

spacelsee标签

会删除html标签之间的空白
  1. {% spaceless %}  
  2.     <div>  
  3.         <strong>foo</strong>  
  4.     </div>  
  5. {% endspaceless %}  
  6.   
  7. {# output will be <div><strong>foo</strong></div> #}  

autoescape标签

这个十分汗颜,我居然没看懂。我只知道字面上的意思是自动转义。。但是。。我做实验的时候 还是不知道应怎么使用
他官方给的例子是
  1. {% autoescape true %}  
  2.     Everything will be automatically escaped in this block  
  3. {% endautoescape %}  
  4.   
  5. {% autoescape false %}  
  6.     Everything will be outputed as is in this block  
  7. {% endautoescape %}  
  8.   
  9. {% autoescape true js %}  
  10.     Everything will be automatically escaped in this block  
  11.     using the js escaping strategy  
  12. {% endautoescape %}  

而我这么测试。输出的还是原本的内容。
  1. {% autoescape true %}  
  2.     <body><b>aaaa</b></body>  
  3. {% endautoescape %}  
  4.   
  5. {% autoescape false %}  
  6.     <b>aaaa</b>  
  7. {% endautoescape %}  
  8.   
  9. {% autoescape true js %}  
  10.     <script>  
  11.     function aaa(){alert('x');}  
  12.     </script>  
  13. {% endautoescape %}  

这个请教各位路过的师兄了。。。
他官方文档还说,如果使用了 {% autoescape true %} 那么里面的内容都会被转义成安全的内容,除非你使用raw过滤器。
  1. {% autoescape true %}  
  2.     {{ safe_value|raw }}  
  3. {% endautoescape %}  
另外,twig里函数的返回值都是安全的比如 macros parent 
 

raw标签

raw标签,保证区块内的数据不被模板引擎解析。
  1. {% raw %}  
  2.     <ul>  
  3.     {% for item in seq %}  
  4.         <li>{{ item }}</li>  
  5.     {% endfor %}  
  6.     </ul>  
  7. {% endraw %}  

flush标签

1.5版本新增内容
告诉模板,刷新输出缓存,在内部其实是调用了php的flush函数
  1. {% flush %}  

do 标签

1.5版本新增内容
do 标签的作用就像是输出标签一样{{ }},他可以计算一些表达式,区别是不打印出任何东西
  1. {% do 1 + 2 %}  
 
标签的学习到此结束了。掌声鼓励下。。。。。下面进入过滤器的学习。。。。。。呱唧呱唧
原文地址:https://www.cnblogs.com/Felixdh/p/3419172.html