Twig for 开发者
原文:Twig for Developers 翻译:小虾米(QQ:509129)
Twig for 开发者
本章描述了Twig的API,而不是模板语言。这将是最有用的参考对于那些实现模板接口的用户来说,而不是那些创建Twig模板的人来说。
基础知识(Basics)
Twig使用一个名为环境(environment)的中心对象(类Twig_Environment)。该类的实例用于存储配置和扩展,用于从文件系统或其他位置加载模板。
大多数应用程序将在应用程序初始化时创建一个Twig_Environment对象,并将其用于加载模板。在某些情况下,如果使用不同的配置,那么有多个环境并排使用是非常有用的。
配置Twig到加载模板的最简单方法是这样的:
require_once '/path/to/vendor/autoload.php';
$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
'cache' => '/path/to/compilation_cache',
));
这将创建一个带有默认设置的模板环境和一个加载器,它会查找/ path / to / templates /文件夹中的模板。不同的加载器是可用的,如果想从数据库或其他资源加载模板,也可以编写自己的文件。
注意,环境(environment)的第二个参数是一系列选项。缓存选项是一个编译缓存目录,其中Twig缓存已编译的模板,以避免对次序列请求的解析阶段。它与您可能想要为评估的模板添加的缓存非常不同。对于这样的需求,您可以使用任何可用的PHP缓存库。
渲染模板(Rendering Templates)
要从Twig环境中加载模板,请调用load()方法,该方法返回Twig_TemplateWrapper实例:
$template = $twig->load('index.html');
要使用一些变量来呈现模板,请调用render()方法:
echo $template->render(array('the' => 'variables', 'go' => 'here'));
display()方法是直接输出模板的快捷方式。
您还可以加载并呈现模板一次搞定:
echo $twig->render('index.html', array('the' => 'variables', 'go' => 'here'));
如果模板定义了块,则可以通过renderBlock()调用来单独呈现它们:
echo $template->renderBlock('block_name', array('the' => 'variables', 'go' => 'here'));
环境选项(Environment Options)
当创建一个新的Twig_Environment实例时,可以将一系列选项作为构造函数的第二个参数:
$twig = new Twig_Environment($loader, array('debug' => true));
以下选项可供选择:
debug 布尔类型(boolean)
当设置为true时,生成的模板有一个__toString()方法,您可以使用它来显示生成的节点(默认为false)。
charset 字符串类型(string)(默认为utf-8)
用于生成模板的基础模板类。
cache 字符串类型(string) 或 false
一个绝对路径,用于存储已编译的模板,或者是false来禁用缓存(这是默认的)。
auto_reload 布尔类型(boolean)
当使用Twig进行开发时,每当源代码发生变化时重新编译模板是很有用的。如果您不为auto_reload选项提供一个值,那么它将根据调试值自动确定。
strict_variables 布尔类型(boolean)
如果设置为false,Twig将静默地忽略无效的变量(不存在的变量和属性/方法),并以null值替换它们。当设置为true时,Twig会抛出一个异常(默认为false)。
autoescape 字符串类型(string)
设置默认的自动转义策略(名称、html、js、css、url、html_attr,或一个PHP回调,它接受模板“文件名”并返回转义策略的使用——回调不能是一个函数名,以避免与内置的转义策略发生冲突);设置为false来禁用自动转义。名称逃逸策略决定了基于模板文件名扩展的模板的转义策略(这一策略不会在运行时造成任何开销,因为自动转义是在编译时完成的)。
optimizations 整型类型(integer)
一个标志(默认为- 1)的标志(默认为- 1),所有的优化都被启用;将其设置为0来禁用。
加载器(Loaders)
加载程序负责从资源(如文件系统)加载模板。
编译缓存(Compilation Cache)
所有模板加载器都可以在文件系统上缓存已编译的模板,以备将来重用。它加速了Twig的速度,因为模板只编译一次;如果使用APC这样的PHP加速器,性能的提升就会更大。请参阅上面的缓存和auto_reload选项以获得更多信息。
内置的加载器(Built-in Loaders)
下面是内置的loaders Twig提供的列表:
Twig_Loader_Filesystem
Twig_Loader_Filesystem从文件系统加载模板。这个加载器可以在文件系统的文件夹中找到模板,并且是加载它们的首选方法:
$loader = new Twig_Loader_Filesystem($templateDir);
它还可以在一系列目录中寻找模板:
$loader = new Twig_Loader_Filesystem(array($templateDir1, $templateDir2));
有了这样的配置,Twig将首先在$ templateDir1中寻找模板,如果它们不存在,那么它就会在$ templateDir2中寻找它们。
您可以通过addPath()和prependPath()方法添加或prepend路径:
$loader->addPath($templateDir3);
$loader->prependPath($templateDir4);
文件系统加载器还支持名称空间模板。这允许在有自己的模板路径的不同名称空间中对模板进行分组。
当使用setpath()、addPath()和prependPath()方法时,将名称空间指定为第二个参数(当未指定时,这些方法将在“main”命名空间上执行):
$loader->addPath($templateDir, 'admin');
名称空间模板可以通过特殊的@ namespace_name / template_path符号来访问:
$twig->render('@admin/index.html', array());
Twig_Loader_Filesystem支持绝对和相对路径。使用相对路径是首选的,因为它使缓存键独立于项目根目录(例如,它允许从构建服务器中缓存缓存,其中目录可能与生产服务器上使用的目录不同):
$loader = new Twig_Loader_Filesystem('templates', getcwd().'/..');
当没有将根路径作为第二个参数传递时,Twig会使用getcwd()相对路径。
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文件中可能是有意义的。
当使用带有缓存机制的数组加载程序时,您应该知道每当模板内容“变化”(缓存键是模板的源代码)时,都会生成一个新的缓存键。如果您不想看到缓存失控,您需要自己处理旧的缓存文件。
wig_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.htm模板,Twig将用$ loader2加载它,但是base.html模板将从$ loader1加载。
Twig_Loader_Chain接受任何实现Twig_LoaderInterface的加载器。
还可以通过addLoader()方法添加loaders。
创建自己的加载器
所有加载器都实现Twig_LoaderInterface:
interface Twig_LoaderInterface
{
/**
* Returns the source context for a given template logical name.
*
* @param string $name The template logical name
*
* @return Twig_Source
*
* @throws Twig_Error_Loader When $name is not found
*/
public function getSourceContext($name);
/**
* Gets the cache key to use for the cache for a given template name.
*
* @param string $name The name of the template to load
*
* @return string The cache key
*
* @throws Twig_Error_Loader When $name is not found
*/
public 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
*
* @return bool true if the template is fresh, false otherwise
*
* @throws Twig_Error_Loader When $name is not found
*/
public function isFresh($name, $time);
/**
* Check if we have the source code of a template, given its name.
*
* @param string $name The name of the template to check if we can load
*
* @return bool If the template source code is handled by this loader or not
*/
public function exists($name);
}
如果当前缓存的模板仍然是新鲜的,给定了最后的修改时间,或者其他错误,则isFresh()方法必须返回true。
getSourceContext()方法必须返回Twig_Source的一个实例。
使用扩展(Using Extensions)
Twig扩展是将新特性添加到Twig的包。使用扩展很简单就是使用addExtension()方法:
$twig->addExtension(new Twig_Extension_Sandbox());
Twig与以下扩展捆绑在一起:
Twig_Extension_Core:定义Twig的所有核心特性。
Twig_Extension_Escaper:添加自动输出-转义,以及避免/无法避免代码块的可能性。
Twig_Extension_Sandbox:将沙箱模式添加到默认的Twig环境中,从而安全评估不受信任的代码。
Twig_Extension_Profiler:启用了内置的Twig分析器。
twig_extension_优化:在编译之前优化节点树。
核心、逃避者和优化器扩展不需要添加到Twig环境中,因为它们是默认注册的。
内置扩展(Built-in Extensions)
本节描述内置扩展添加的特性。
阅读关于扩展Twig的章节,了解如何创建自己的扩展。
核心扩展(Core Extension)
核心扩展定义了Twig的所有核心特性:
转义扩展(Escaper Extension)
转义扩展增加了自动输出转义到Twig。它定义了一个标签、autoescape和一个过滤器,raw。
在创建转义扩展时,您可以打开或关闭全局输出转义策略:
$escaper = new Twig_Extension_Escaper('html');
$twig->addExtension($escaper);
如果设置为html,模板中的所有变量都可以通过(使用html转义策略),除非使用raw过滤器:
{{ article.to_html|raw }}
您还可以使用自动转义标签改变本地的转义模式:
{% 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 #}
如果链中的最后一个过滤器对于当前上下文(例如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 Extension)
可以使用sandbox扩展来评估不受信任的代码。禁止使用不安全的属性和方法。沙箱安全性由策略实例管理。默认情况下,Twig附带一个策略类: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标记和上过滤器。此外,模板只能调用getTitle()和getBody()方法在文章对象上,以及标题和主体公共属性。其他的都不允许,并生成Twig_Sandbox_SecurityError异常。
策略对象是sandbox构造函数的第一个参数:
$sandbox = new Twig_Extension_Sandbox($policy);
$twig->addExtension($sandbox);
默认情况下,sandbox模式是禁用的,当使用sandbox标记包含不受信任的模板代码时,应该启用这个模式:
{% sandbox %}
{% include 'user.html' %}
{% endsandbox %}
您可以将所有模板都通过true作为扩展构造函数的第二个参数:
$sandbox = new Twig_Extension_Sandbox($policy, true);
分析器扩展(Profiler Extension)
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兼容的格式:
$dumper = new Twig_Profiler_Dumper_Blackfire();
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
上传资料,以使其可视化(先创建一个免费帐户):
blackfire --slot=7 upload /path/to/profile.prof
优化器扩展(Optimizer Extension)
优化器扩展在编译之前优化节点树:
$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,在可能的情况下,通过移除循环变量的创建来优化for标记。
Twig_NodeVisitor_Optimizer::OPTIMIZE_RAW_FILTER,尽可能删除raw过滤器。
Twig_NodeVisitor_Optimizer::OPTIMIZE_VAR_ACCESS,可以在可能的情况下简化编译时模板中的变量的创建和访问。
异常(Exceptions)
Twig可以抛出异常:
Twig_Error:所有错误的基本异常。
Twig_Error_Syntax:抛出来告诉用户模板语法有问题。
Twig_Error_Runtime:当运行时发生错误时抛出(例如,当一个过滤器不存在时)。
Twig_Error_Loader:在模板加载过程中抛出错误。
Twig_Sandbox_SecurityError:当一个不允许的标记、过滤器或方法被调用在一个沙盒模板中时抛出。
Last updated
Was this helpful?