• [学习笔记] 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 %}  
     
    标签的学习到此结束了。掌声鼓励下。。。。。下面进入过滤器的学习。。。。。。呱唧呱唧
  • 相关阅读:
    线段树学习笔记
    树状数组学习笔记
    P1816 忠诚 ST表模版
    NOIP 2017 D1T2 时间复杂度
    Ubuntu镜像源
    字符串数据结构模板
    白书的一些奇怪模板
    高精度模板
    大整数类模板
    线段树模板1
  • 原文地址:https://www.cnblogs.com/Felixdh/p/3419172.html
Copyright © 2020-2023  润新知