#面向開發者
這一章介紹 Twig的API而非模版語言。這是針對實現模板接口的最有用的參考,而不是針對創建Twig模板。
##基礎
Twig 使用一個名為 **environment** 的中心對象(它是``Twig_Environment``類的對象)。這個類的實例用于存儲配置和擴展,以及從文件系統或其他位置加載模版。
大多數應用程序會在初始化的時候創建一個 ``Twig_Environment`` 對象,并用它來加載模板。在某些情況下,如果在使用多個不同的配置,是可以讓多個環境存在使用的。
為應用程序配置Twig加載模板的最簡單方式大概是這樣的:
require_once '/path/to/lib/Twig/Autoloader.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
'cache' => '/path/to/compilation_cache',
));
這將會創建一個帶默認設置的模板環境()environment,以及一個在 ``/path/to/templates/`` 查找模版的加載器。不同的加載器都是可用的,如果你像從數據庫或者其他來源加載模版,你也可以自己寫一個加載器。
注意:
> 值得注意的是,環境(environment)的第二個參數是一個環境選項數組。其中的``cache``選項表示編譯緩存目錄,Twig將編譯過的模板緩存在這個目錄中以避免解析階段的重復請求。這與你可能想要為評估后的模版添加的緩存有很大的區別。對于這樣的需求,你可以使用其他PHP緩存庫。
要從環境中加載模版,只需要調用``loadTemplate()``方法即可,它會返回一個``Twig_Template``實例:
$template = $twig->loadTemplate('index.html');
要渲染帶有變量的模板,調用``render()``方法:
echo $template->render(array('the' => 'variables', 'go' => 'here'));
注意:
> ``display()``方法是直接輸出模版的快捷方式。
你還可以一步完成模板的加載和渲染:
echo $twig->render('index.html', array('the' => 'variables', 'go' => 'here'));
##環境選項
在創建一個新的 ``Twig_Environment`` 實例時,你可以傳遞一個選項數組作為構造函數的第二個參數:
$twig = new Twig_Environment($loader, array('debug' => true));
有以下這些可用選項:
* ``debug`` *boolean*
設置為``true``時,生成的模版會有一個 ``__toString()`` 方法,可以用它來宣誓生成的節點。(默認設置是``false``)。
* ``charset`` *string (默認``utf-8``)*
用于模板的字符集。
* ``base_template_class`` *string (默認 ``Twig_Template``)*
用于生成的模板的基礎模板類。
* ``cache`` *string|false*
存儲編譯后的模板的絕對路徑,或者設為 ``false``來禁用緩存(默認``false``)。
* ``auto_reload`` *boolean*
在使用Twig進行開發時,這有助于在源代碼修改時隨時進行重新編譯。如果不為``auto_reload``選項設置值,它會自動根據``debug``選項的值被設定。
* ``strict_variables`` *boolean*
如果設置為 ``false``,Twig會靜默忽略無效的變量(包括變量、不存在的屬性和方法),并以``null``值替換它們。如果將其設置為 ``true``,Twig則會拋出一個異常(默認是``false``)。
* ``autoescape`` *string|boolean*
如果設置為``true``,會默認為所有模板棄用HTML自動轉義(默認是``true``)。
從Twig 1.8版開始,你可以將轉義策略設置為(``html``, ``js``,
或者用``false``禁用)。
從Twig 1.9版開始,你可以將轉義策略設置為(``css``, ``url``, ``html_attr``, or a PHP callback that takes the template "filename" and must return the escaping strategy to use -- the callback cannot be a function name to avoid collision with built-in escaping strategies)。
從Twig 1.17開始 , ``filename``轉義策略決定了用于基于模板文件名擴展的模板的轉義策略(由于自動轉義在編譯時就已經完成,所以本策略不會產生任何開銷)
* ``optimizations`` *integer*
此處的標記表示哪種優化方式將被應用(默認是``-1`` —— 所有的優化設置都被棄用;設置為``0``,則禁用)。
##加載器(Loader)
加載器負責從文件系統之類的來源加載模板。
###編譯緩存
所有模板加載器都可以在文件系統中緩存編譯后的模板以便將來重用。模板只需要編譯一次就能為Twig提速不少,并且如果使用了APC之類的加速器,還能帶來更大的性能提升。查看前文中``Twig_Environment``的``cache``和``auto_reload``兩個選項了解更多信息。
###內置的加載器
這是一個由Twig提供的內置加載器列表:
####``Twig_Loader_Filesystem``
> 在 Twig 1.10版中,加入了 ``prependPath()``,并支持命名空間。
``Twig_Loader_Filesystem``從文件系統加載模板。這個加載器可以從文件系統目錄中找到模板,這是加載模板的最佳方式:
$loader = new Twig_Loader_Filesystem($templateDir);
它還可以從由多個目錄組成的數組中尋找模板:
$loader = new Twig_Loader_Filesystem(array($templateDir1, $templateDir2));
按照這樣的配置,Twig會首先在 ``$templateDir1`` 中查找模板,如果沒有,則回退,然后在 ``$templateDir2`` 中繼續查找模板。
還可以通過``addPath()`` 和 ``prependPath()``方法添加或預設路徑:
$loader->addPath($templateDir3);
$loader->prependPath($templateDir4);
文件系統加載器還支持命名空間模板。這允許將擁有各種路徑的模板組織到不同的命名空間下》
在使用 ``setPaths()``, ``addPath()``, 和 ``prependPath()`` 方法時,將命名空間指定為第二個參數,如果沒有指定,這些方法會調用主(main)命名空間:
$loader->addPath($templateDir, 'admin');
命名空間模板可以用通過特定的 ``@namespace_name/template_path``符號訪問:
$twig->render('@admin/index.html', array());
####``Twig_Loader_Array``
使用``Twig_Loader_Array``從PHP數組加載模板。它被傳遞一個綁定模板名稱的字符串數組:
~~~
$loader = new Twig_Loader_Array(array(
'index.html' => 'Hello {{ name }}!',
));
$twig = new Twig_Environment($loader);
echo $twig->render('index.html', array('name' => 'Fabien'));
~~~
這個加載器對于單元測試非常有用。它還可以用于將所有模板存放在單個PHP文件內的小型項目,的確可以這樣做。
提示:
> 在使用帶有緩存極致的 ``Array`` 或 ``String`` 加載器時,你應當明白新的緩存鍵時在每次模板內容改變時生成的(緩存鍵是指模板的源代碼)。如果不希望緩存失控地增加,你需要注意自行清除舊的緩存。
####``Twig_Loader_Chain``
``Twig_Loader_Chain`` 將模板的加載工作委派給其他加載器:
$loader1 = new Twig_Loader_Array(array(
'base.html' => '{% block content %}{% endblock %}',
));
$loader2 = new Twig_Loader_Array(array(
'index.html' => '{% extends "base.html" %}{% block content %}Hello {{ name }}{% endblock %}',
'base.html' => 'Will never be loaded',
));
$loader = new Twig_Loader_Chain(array($loader1, $loader2));
$twig = new Twig_Environment($loader);
在查找模板時,Twig會輪流嘗試每個加載器,并在找到模板時立即返回。前面的例子中,在渲染 ``index.html``模板時,Twig 會使用``$loader2``來加載它,但``base.html``模板會從``$loader1``中被加載。
``Twig_Loader_Chain`` 能接收任意實現了 ``Twig_LoaderInterface``接口的加載器。
注意:
> 你還可以使用``addLoader()`` 方法來添加加載器。
###創建你自己的加載器
所有的加載器都實現了 ``Twig_LoaderInterface``:
interface Twig_LoaderInterface
{
/**
* Gets the source code of a template, given its name.
*
* @param string $name string The name of the template to load
*
* @return string The template source code
*/
function getSource($name);
/**
* Gets the cache key to use for the cache for a given template name.
*
* @param string $name string The name of the template to load
*
* @return string The cache key
*/
function getCacheKey($name);
/**
* Returns true if the template is still fresh.
*
* @param string $name The template name
* @param timestamp $time The last modification time of the cached template
*/
function isFresh($name, $time);
}
考慮到最后修改的時間,如果當前被緩存的模板仍然是最新的,則 ``isFresh()`` 方法必須返回 ``true``,否則返回``false``。
提示:
> 從Twig 1.11.0 開始,你還可以實現 ``Twig_ExistsLoaderInterface``,讓你的加載器在使用鏈式加載器時更快速。
##使用擴展
Twig的擴展程序其實是為Twig添加新特性的包(package)。使用擴展跟使用 ``addExtension()`` 方法一樣簡單:
$twig->addExtension(new Twig_Extension_Sandbox());
Twig comes bundled with the following extensions:
* *Twig_Extension_Core*: 定義Twig的所有核心特性。
* *Twig_Extension_Escaper*: 為代碼塊添加自動化輸出轉義以及是否轉義的可能性。
* *Twig_Extension_Sandbox*: 為默認的Twig環境添加沙河模式,使其能安全地評估未受信任的代碼。
* *Twig_Extension_Profiler*: 啟用內置的Twig分析器(Twig 1.18版本以上可用)。
* *Twig_Extension_Optimizer*: 在編譯前優化節點樹。
上面的 core, escaper, 以及 optimizer 擴展不是必須要添加到 Twig環境中,因為它們都是默認已被注冊的。
##內置的擴展
這一節介紹由內置擴展添加的特性
提示:
> 這一章是關于擴展Twig的,閱讀這一章學習如何創建你自己的擴展。
###核心擴展``core``
``core``擴展定義Twig的所有核心特性:
* Tags
* Filters
* Functions
* Tests
###轉義擴展``Escaper``
使用 ``escaper`` 擴展,為Twig添加動態輸出轉義。它定義了``autoescape``標簽和 ``raw``過濾器。
在創建轉義擴展時,你可以打開或者關閉全局輸出轉義策略:
$escaper = new Twig_Extension_Escaper('html');
$twig->addExtension($escaper);
如果將其設置為 ``html``,模板中的所有變量都會被轉義(使用``html``轉義策略), 除非是用了 ``raw`` 過濾器。:
{{ article.to_html|raw }}
還可以使用 ``autoescape`` 標簽來局部地改變轉義模式(查看 autoescape 文檔,了解Twig 1.8以上的語法):
{% autoescape 'html' %}
{{ var }}
{{ var|raw }} {# var won't be escaped #}
{{ var|escape }} {# var won't be double-escaped #}
{% endautoescape %}
警告:
> ``autoescape`` 對引入的文件沒有影響。
像下面這樣實現轉義規則:
* 在模板中直接用作變量或過濾器參數的字面值(包括整型數、布爾值、數組等)**從不**被自動轉義:
{{ "Twig<br />" }} {# won't be escaped #}
{% set text = "Twig<br />" %}
{{ text }} {# will be escaped #}
* 被標注為安全的,其結果總是一個字面值或變量的表達式,**從不**被自動轉義:
{{ foo ? "Twig<br />" : "<br />Twig" }} {# won't be escaped #}
{% set text = "Twig<br />" %}
{{ foo ? text : "<br />Twig" }} {# will be escaped #}
{% set text = "Twig<br />" %}
{{ foo ? text|raw : "<br />Twig" }} {# won't be escaped #}
{% set text = "Twig<br />" %}
{{ foo ? text|escape : "<br />Twig" }} {# the result of the expression won't be escaped #}
* 轉義應用于打印之前,和其他過濾器應用之后:
{{ var|upper }} {# is equivalent to {{ var|upper|escape }} #}
* `raw`過濾器只能用在過濾器鏈的結尾:
{{ var|raw|upper }} {# will be escaped #}
{{ var|upper|raw }} {# won't be escaped #}
* 如果當前上下文(context,例如``html``或``js``)的過濾器鏈中最后一個過濾器被標注為安全,那么自動轉義不會被應用。``escape`` 和 ``escape('html')`` 用于將 HTML標注為安全,``escape('js')`` 用于將JavaScript標注為安全,``raw``可以將任意內容標注為安全:
{% autoescape 'js' %}
{{ var|escape('html') }} {# will be escaped for HTML and JavaScript #}
{{ var }} {# will be escaped for JavaScript #}
{{ var|escape('js') }} {# won't be double-escaped #}
{% endautoescape %}
注意:
> 自動轉義有一些局限性,因為針對表達式的轉義是在評估之后才應用的。舉個例子,在處理連接時,``{{ foo|raw ~ bar }}`` 不會給出預期結果,因為轉義是應用于連接的結果上的,而不是應用在單個變量上(所以,``raw``過濾器此時不會生效)。
###沙盒擴展``sandbox``
``sandbox``擴展用于評估未被信任的代碼。禁止訪問不安全的屬性和方法。沙盒的安全性由一個policy實例進行管理。默認地,Twig帶有一個policy類: ``Twig_Sandbox_SecurityPolicy``。這個類允許你為標簽、屬性、方法添加白名單:
$tags = array('if');
$filters = array('upper');
$methods = array(
'Article' => array('getTitle', 'getBody'),
);
$properties = array(
'Article' => array('title', 'body'),
);
$functions = array('range');
$policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties, $functions);
基于上述配置,安全策略僅允許使用``if``標簽和``upper``過濾器。而且,模板只能用``Article``對象調用 ``getTitle()`` 和 ``getBody()`` 方法。其它的用法都被禁止,并會生成一個 ``Twig_Sandbox_SecurityError`` 異常。
策略對象 policy 是沙盒構造函數的第一個參數:
$sandbox = new Twig_Extension_Sandbox($policy);
$twig->addExtension($sandbox);
默認地,沙盒模式是被禁用了的。但在使用``sandbox``標簽引入未被信任的模板代碼時,應當啟用沙盒模式:
{% sandbox %}
{% include 'user.html' %}
{% endsandbox %}
可以通過將 extension 構造函數的第二個參數設置為``true``,將所有模板放入沙盒中:
$sandbox = new Twig_Extension_Sandbox($policy, true);
###分析器擴展``profiler``
> 在 Twig 1.18 添加了分析器擴展
分析器擴展``profiler``為Twig模板啟用了分析器;由于它增加了一些開銷,所以只能在開發環境中使用它:
$profile = new Twig_Profiler_Profile();
$twig->addExtension(new Twig_Extension_Profiler($profile));
$dumper = new Twig_Profiler_Dumper_Text();
echo $dumper->dump($profile);
一份分析結果包含了模板、代碼塊、以及指令執行的時間和內存消耗等信息
可以將分析數據轉換成 [Blackfire.io](https://blackfire.io/) 兼容的格式:
$dumper = new Twig_Profiler_Dumper_Blackfire();
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
將分析結果上傳,使其可視化(需要先[創建一個賬號](https://blackfire.io/signup)):
blackfire --slot=7 upload /path/to/profile.prof
###優化器擴展``potimizer``
優化器擴展 ``optimizer`` 在編譯前優化節點樹:
$twig->addExtension(new Twig_Extension_Optimizer());
默認地,所有優化項都是開啟了的。你可以通過將某些你想要啟用的優化項傳遞給構造函數,以開啟它們:
$optimizer = new Twig_Extension_Optimizer(Twig_NodeVisitor_Optimizer::OPTIMIZE_FOR);
$twig->addExtension($optimizer);
Twig 支持以下優化項:
* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_ALL``, 啟用所有優化項(這是默認值)
* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_NONE``, 禁用所有優化項。這會減少編譯時間,但會增加執行時間和內存消耗。
* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_FOR``, 如果可以,則通過移除``loop``變量的創建來優化``for``標簽。
* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_RAW_FILTER``, 如果可能,則移除 ``raw`` 過濾器。
* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_VAR_ACCESS``, 如果可能,則簡化已編譯模板中變量的創建和訪問。
##異常
Twig 可以拋出異常:
* ``Twig_Error``: 所有錯誤的基礎異常》
* ``Twig_Error_Syntax``: 拋出此異常,表示模板語法存在問題。
* ``Twig_Error_Runtime``: 在運行時刻(runtime)重現了某個錯誤,則拋出這個異常(比如某個過濾器并不存在)
* ``Twig_Error_Loader``: 在模板加載過程中重現了某個錯誤,則拋出這個異常。
* ``Twig_Sandbox_SecurityError``: 在沙盒模式模板中調用了某個未被允許的標簽、過濾器或方法時,拋出這個異常。
- 首頁
- 目錄
- 介紹
- 安裝
- 面向模板設計師
- 面向開發者
- 擴展 Twig
- Twig的內部構建
- 棄用的特性
- 使用技巧
- 代碼規范
- 標簽 tags
- autoescape
- block
- do
- embed
- extends
- filter
- flush
- for
- from
- if
- import
- include
- macro
- sandbox
- set
- spaceless
- use
- verbatim
- 過濾器
- abs
- batch
- capitalize
- convert_encoding
- date
- date_modify
- default
- escape
- first
- format
- join
- json_encode
- keys
- last
- length
- lower
- merge
- nl2br
- number_format
- raw
- replace
- reverse
- round
- slice
- sort
- split
- striptags
- title
- trim
- upper
- url_encode
- 函數
- attribute
- block
- constant
- cycle
- date
- dump
- include
- max
- min
- parent
- random
- range
- source
- template_from_string
- 測試
- constant
- defined
- divisibleby
- empty
- even
- iterable
- null
- odd
- sameas