owned this note
owned this note
Published
Linked with GitHub
# 基本語法介紹
本文檔描述了模板引擎的語法(syntax)和語義(semantics),對於創建 Twig 模板的人來說將是最有用的參考。
overview
--
模板是一個普通的文本文件。它可以生成任何基於文本的格式(HTML、XML、CSV、LaTeX 等)。它沒有特定的擴展名稱,可以是.html或者 .xml。
模板包含變量(variables)或表達式(expressions),它們在評估模板時被取代為值,以及控制模板邏輯的標籤。
下面是一個最小的模板,說明了一些基礎知識。我們將在稍後介紹更多詳細信息:
```php=
<!DOCTYPE html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>My Webpage</h1>
{{ a_variable }}
</body>
</html>
```
有兩種分隔符號:```{% ... %}```和```{{ ... }}```。第一個用於執行諸如 for 循環之類的語句,後者輸出表達式的結果。
變量(variable)
---
應用程序將變量傳遞給模板以在模板中進行操作。變量也可能具有您可以訪問的屬性或元素。變量的視覺化表示很大程度上取決於提供它的應用程式。
使用點 ( .) 訪問變量的屬性(PHP object的方法或屬性,或 PHP array的項):
```{{ foo.bar }}```
>實現方法:
>為方便起見foo.bar,在PHP層做了以下幾件事:
>
>檢查是否foo是數組和bar有效元素;
如果不是,如果foo是一個對象,檢查它bar是一個有效的屬性;
如果不是,如果foo是一個對象,檢查它bar是一個有效的方法;
如果不是,如果foo是一個對象,檢查它getBar是一個有效的方法;
如果不是,如果foo是一個對象,檢查它isBar是一個有效的方法;
如果不是,如果foo是一個對象,檢查它hasBar是一個有效的方法;
>如果沒有,則返回一個null值。
> ---Twig 還支持用於訪問 PHP array上的項目的特定語法 foo['bar']:
>檢查是否foo是array和bar有效元素;
如果沒有,則返回一個null值。
如果變量或屬性不存在,null成為strict_variables選項設置為時,您將收到一個值false;或者,如果strict_variables 設置了,Twig 將拋出錯誤(請參閱[環境選項](https://twig.symfony.com/doc/3.x/api.html#environment_options))。
全域變數(global variables)
---
以下變量在模板中始終可用:
- _self: 引用當前模板名稱;
- _context: 引用當前上下文;
- _charset: 引用當前char set。
#### 設置變量
您可以為code block內的變量賦值。使用 set 標籤:
```php=
{% set foo = 'foo' %}
{% set foo = [1, 2] %}
{% set foo = {'foo': 'bar'} %}
```
過濾器(filters)
---
變量可以通過過濾器修改。過濾器通過管道符號 ( |)與變量分開。可以鏈接多個過濾器。一個過濾器的輸出可以應用於下一個。
以下範例從它的name和標題案例中刪除所有 HTML 標籤:
```
{{ name|striptags|title }}
```
接收參數的過濾器在參數周圍有括號。此範例通過逗號連接列表的元素:
```
{{ list|join(', ') }}
```
要對一段代碼應用過濾器,請使用apply標籤將其包裹起來 :
```
{% apply upper %}
This text becomes uppercase
{% endapply %}
```
轉到[過濾器](https://twig.symfony.com/doc/3.x/filters/index.html)頁面以了解有關內置過濾器的更多信息。
functions
---
可以調用函數來生成內容。函數通過其名稱後跟括號 ( () )來調用,並且可以有參數。
例如,該range函數返回一個包含整數等差數列的列表:
```php=
{% for i in range(0, 3) %}
{{ i }},
{% endfor %}
```
轉到[函數](https://twig.symfony.com/doc/3.x/functions/index.html)頁面以了解有關內置函數的更多信息。
命名參數(name arguments)
---
```php=
{% for i in range(low=1, high=10, step=2) %}
{{ i }},
{% endfor %}
```
使用命名參數使您的模板更明確能了解作為參數傳遞的值的含義:
```php
{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
{# versus #}
{{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }}
```
命名參數還允許您跳過一些不想更改默認值的參數:
```php=
{# the first argument is the date format, which defaults to the global date format if null is passed #}
{{ "now"|date(null, "Europe/Paris") }}
{# or skip the format value by using a named argument for the time zone #}
{{ "now"|date(timezone="Europe/Paris") }}
```
您還可以在一次調用中同時使用位置參數和命名參數,在這種情況下,位置參數必須始終位於命名參數之前:
```php=
{{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}
```
:::success
Tip
每個函數和過濾器文件頁面都有一個部分,其中列出了支持的所有參數的名稱。
:::
控制結構
---
控制結構是指控制程式流程的所有事物 - 條件(即if/ elseif/ else)、-for迴圈以及諸如塊之類的事物。控制結構出現在{% ... %} 塊內。
例如,要顯示在名為```users```的變量中提供的使用者清單列表,請使用[for](https://twig.symfony.com/doc/3.x/tags/for.html) tag:
```php=
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
```
所述如果標記可用於測試表達式:
```php=
{% if users|length > 0 %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
```
轉到[標籤](https://twig.symfony.com/doc/3.x/tags/index.html)頁面以了解有關內置標籤的更多信息。
註釋(comments)
---
要註釋掉模板中一行的一部分,請使用註釋語法```{# ...
#}```
這對於debug或為其他模板設計者或您自己添加信息很有用:
```php=
{# note: disabled template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
```
包括(include)其他模板
---
include function對於當前的模板以及include的模板回傳渲染的內容是非常好用的:
```
{{ include('sidebar.html') }}
```
預設情況下,include的模板可以訪問與include它們的模板相同的上下文。這意味著主模板中定義的任何變量也將在include的模板中可用:
```php=
{% for box in boxes %}
{{ include('render_box.html') }}
{% endfor %}
```
包含的模板```render_box.html```能夠訪問該box變量。
模板的名稱取決於模板loader。例如, ```\Twig\Loader\FilesystemLoader```允許您透過提供文件名來訪問其他模板。您可以使用```/```訪問子目錄中的模板:
```
{{ include('sections/articles/sidebar.html') }}
```
此行為取決於嵌入 Twig 的應用程序。
模板繼承
---
Twig 最強大的部分是模板繼承。模板繼承允許您構建一個基本的“骨架”模板,其中包含站點的所有公共元素並定義子模板可以覆蓋的block。
從一個例子開始更容易理解這個概念。
讓我們定義一個基本模板,base.html,它定義了一個可用於兩列頁面的 HTML 框架文檔:
```php=
<!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](https://twig.symfony.com/doc/3.x/tags/block.html)標籤定義了子模板可以填充的四個塊。block標籤所做的就是告訴模板引擎子模板可以覆蓋模板的那些部分。
```
子模板可能如下所示:
```php=
{% 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 to my awesome homepage.
</p>
{% endblock %}
```
[extend](https://twig.symfony.com/doc/3.x/tags/extends.html)標籤是這裡的關鍵。它告訴模板引擎這個模板“擴展”了另一個模板。當模板系統評估這個模板時,它首先定位父模板。extends 標籤應該是模板中的第一個標籤。
請注意,由於子模板未定義footer塊,因此使用來自父模板的值。
可以使用parent函數渲染父塊的內容 。這將返回父塊的結果:
```
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ parent() }}
{% endblock %}
```
:::success
Tip
extends標籤的文檔頁面描述了更高級的特性,比如塊嵌套、範圍、動態繼承和條件繼承。
:::
HTML 轉義(escaping)
---
從模板生成 HTML 時,始終存在變量包含影響生成的 HTML 的字符的風險。有兩種方法:手動轉義每個變量或預設自動轉義所有變量。
Twig 兩者都支持,默認情況下啟用自動轉義。
自動轉義策略可以通過[autoescape](https://twig.symfony.com/doc/3.x/api.html#environment_options)選項配置 ,默認為html.
使用手動轉義
如果啟用了手動轉義,則您有責任在需要時轉義變量。逃避什麼?來自不受信任來源的任何變量。
使用轉義或e過濾器進行轉義:
```
{{ user.username|e }}
```
默認情況下,escape過濾器使用該html策略,但根據轉義上下文,您可能希望顯式使用其他策略:
```
{{ user.username|e('js') }}
{{ user.username|e('css') }}
{{ user.username|e('url') }}
{{ user.username|e('html_attr') }}
```
使用自動轉義
無論是否啟用自動轉義,您都可以使用autoescape 標籤標記模板的一部分是否要轉義:
```
{% autoescape %}
Everything will be automatically escaped in this block (using the HTML strategy)
{% endautoescape %}
```
預設情況下,自動轉義使用html轉義策略。如果在其他上下文中輸出變量,則需要使用適當的轉義策略顯式轉義它們:
```
{% autoescape 'js' %}
Everything will be automatically escaped in this block (using the JS strategy)
{% endautoescape %}
```
escaping
---
有時需要甚至有必要讓 Twig 忽略它本來會作為變量或block處理的部分。例如,如果使用預設語法並且您想```{{```在模板中用作原始字串而不是啟動變量,則必須使用技巧。
最簡單的方法是```({{)```使用變量表達式輸出變量分隔符:
```
{{ '{{' }}
```
對於較大的部分,逐字標記一個block [verbatim](https://twig.symfony.com/doc/3.x/tags/verbatim.html)是有意義的 。
宏(macros)
---
宏可與常規編程語言中的函數相媲美。它們有助於重用 HTML 片段而不是重複自己。它們在宏標記[文件](https://twig.symfony.com/doc/3.x/tags/macro.html)中進行了描述 。
表達式
---
Twig 允許在任何地方使用表達式。
>Note
運算符優先級如下,優先級最低的運算符首先列出:(?:三元運算符), b-and, b-xor, b-or, or, and, ==, !=, <=>, <, >, >=, <=, in, matches, starts with, ends with, .., +, -, ~, *, /, //, %, is(tests), **, ??、| (過濾器)、[]、 和.:
```php=
{% set greeting = 'Hello ' %}
{% set name = 'Fabien' %}
{{ greeting ~ name|lower }} {# Hello fabien #}
{# use parenthesis to change precedence #}
{{ (greeting ~ name)|lower }} {# hello fabien #}
```
文字(literals)
---
最簡單的表達式形式是文字。文字是 PHP 類型的表示,例如字串、數字和array。存在以下文字:
- "Hello World": 兩個雙引號或單引號之間的所有內容都是字串。當您需要模板中的字符時(例如作為函數調用的參數、過濾器或僅用於擴展或包含模板)。一個字串可以包含一個分隔符號,如果它前面有一個反斜杠 ( \)——就像在'It\'s good'. 如果字符串包含反斜杠(例如'c:\Program Files'),則通過```\\```(例如'c:\\Program Files')將其轉義。
- 42/ 42.23: 整數和浮點數是通過寫下數字來創建的。如果存在點,則數字為浮點數,否則為整數。
- ["foo", "bar"]: array 由以逗號 ( , )分隔並用方括號 ( [] )包裹的表達式序列定義。
- {"foo": "bar"}:hash 由以逗號 ( , )分隔並用大括號 ( {} )包裹的鍵和值列表定義:
```php=
{# keys as string #}
{ 'foo': 'foo', 'bar': 'bar' }
{# keys as names (equivalent to the previous hash) #}
{ foo: 'foo', bar: 'bar' }
{# keys as integer #}
{ 2: 'foo', 4: 'bar' }
{# keys can be omitted if it is the same as the variable name #}
{ foo }
{# is equivalent to the following #}
{ 'foo': foo }
{# keys as expressions (the expression must be enclosed into parentheses) #}
{% set foo = 'foo' %}
{ (foo): 'foo', (1 + 1): 'bar', (foo ~ 'b'): 'baz' }
```
- true/ false:true代表真值,false 代表假值。
- null:null表示沒有特定值。這是當變量不存在時返回的值。none是 的別名null。
array和hashes可以嵌套(nested):
```{% set foo = [1, {"foo": "bar"}] %}```
:::success
Tip
使用雙引號或單引號字串對性能沒有影響,但僅在雙引號字串中支持字串插值。
:::
數學
---
Twig 允許您在模板中進行數學運算;支持以下運算符:
- +: 將兩個數字相加(操作數被轉換為數字)。{{1 + 1 }}是2。
- -: 從第一個數字中減去第二個數字。{{ 3 - 2 }}是 1。
- /: 將兩個數字相除。返回值將是一個浮點數。{{ 1 / 2 }}是{{ 0.5 }}。
- %: 計算整數除法的餘數。{{ 11 % 7 }}是 4。
- //: 將兩個數字相除並返回地板整數結果。{{ 20// 7 }}is 2, {{ -20 // 7 }}is -3(這只是round filter的語法糖)。
- *: 將左操作數與右操作數相乘。{{ 2 * 2 }}會回傳4。
- **:將左操作數提高到右操作數的冪。{{ 2 **3 }}會回傳8。
邏輯
---
您可以使用以下運算符組合多個表達式:
- and: 如果左右操作數都為真,則返回真。
- or: 如果左操作數或右操作數為真,則返回真。
- not: 否定一個陳述。
- (expr): 對錶達式進行分組。
比較
---
下列比較運算符支持在任何表達式:==, !=,<,>,>=,和<=。
您還可以檢查字串starts with或ends with其他字符串:
```php=
{% if 'Fabien' starts with 'F' %}
{% endif %}
{% if 'Fabien' ends with 'n' %}
{% endif %}
```
>Note
對於復雜的字符串比較,該matches運算允許您使用正則表達式:
```php=
{% if phone matches '/^[\\d\\.]+$/' %}
{% endif %}
```
containment operator
---
in運算子進行安全測試。如果左側的運算元包含於右側則回傳true:
```php=
{# returns true #}
{{ 1 in [1, 2, 3] }}
{{ 'cd' in 'abcde' }}
```
要執行否定測試,請使用not in運算符:
```php=
{% if 1 not in [1, 2, 3] %}
{# is equivalent to #}
{% if not (1 in [1, 2, 3]) %}
```
測試運算子
---
is進行測試。測試可用於針對公共表達式測試變量。正確的運算元是測試的名稱:
```
{# find out if a variable is odd #}
{{ name is odd }}
```
測試也可以接受參數:
```
{% if post.status is constant('Post::PUBLISHED') %}
```
可以使用is not運算符否定測試:
```
{% if post.status is not constant('Post::PUBLISHED') %}
{# is equivalent to #}
{% if not (post.status is constant('Post::PUBLISHED')) %}
```
轉到[測試](https://twig.symfony.com/doc/3.x/tests/index.html)頁面以了解有關內置測試的更多信息。
其他運算子
---
以下運算符不屬於任何其他類別:
- |:應用過濾器。
- ..: 根據操作符前後的操作數創建一個序列(這是范圍函數的語法糖):
```
{{ 1..5 }}
{# equivalent to #}
{{ range(1, 5) }}
```
請注意,由於運算符號優先級規則,將其與過濾運算符組合時必須使用括號:
```(1..5)|join(', ')```
- ~: 將所有操作數轉換為字符串並將它們連接起來。{{ "Hello" ~ name ~ "!" }}會返回(假設name是'John')Hello John!。
- ., []: 獲取變量的屬性。
- ?:: 三元運算符:
```
{{ foo ? 'yes' : 'no' }}
{{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }}
{{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
```
??:空合併運算符:
```
{# returns the value of foo if it is defined and not null, 'no' otherwise #}
{{ foo ?? 'no' }}
```
字串插值
---
字串插值 ( #{expression}) 允許任何有效的表達式出現在雙引號字符串中。將該表達式的計算結果插入到字符串中:
```
{{ "foo #{bar} baz" }}
{{ "foo #{1 + 2} baz" }}
```
空白控制
---
模板標籤後的第一個換行會被自動刪除(就像在 PHP 中一樣)。模板引擎不會進一步修改空格,因此每個空格(空格、製表符、換行符等)都將原樣返回。
您還可以在每個標籤級別控制空格。通過在標籤上使用空格控制修飾符,您可以修改頭尾的空格。
Twig 支持兩個修飾符:
- 通過```-```修飾符修剪空白:刪除所有空白(包括換行);
- 通過```~```修飾符修剪行空白:刪除所有空白(不包括換行)。在右側使用此修飾符會禁用從 PHP 繼承的第一個換行的預設刪除。
修飾符號可以用在標籤的任一側,例如 ```in{%-或-%}``` ,它們會消耗標籤那一側的所有空白。可以在標籤的一側或兩側使用修飾符:
```php=
{% set value = 'no spaces' %}
{#- No leading/trailing whitespace -#}
{%- if true -%}
{{- value -}}
{%- endif -%}
{# output 'no spaces' #}
<li>
{{ value }} </li>
{# outputs '<li>\n no spaces </li>' #}
<li>
{{- value }} </li>
{# outputs '<li>no spaces </li>' #}
<li>
{{~ value }} </li>
{# outputs '<li>\nno spaces </li>' #}
```
:::success
Tip
除了空格修飾符之外,Twig 還有一個spaceless過濾器可以去除HTML 標籤之間的空格:
{% apply spaceless %}
<div>
<strong>foo bar</strong>
</div>
{% endapply %}
{# output will be <div><strong>foo bar</strong></div> #}
:::
擴展(extensions)
---
tiwg可以擴展。如果您想創建自己的擴展,請閱讀[創建extension](https://twig.symfony.com/doc/3.x/advanced.html#creating_extensions)。
code standard
---
以下還有官方建議的編碼標準,可點此[參考](https://twig.symfony.com/doc/3.x/coding_standards.html)