# Twig for 开发者

> 原文：[Twig for Developers](https://twig.sensiolabs.org/doc/2.x/api.html)\
> 翻译：小虾米（QQ:509129）

## Twig for 开发者

本章描述了Twig的API，而不是模板语言。这将是最有用的参考对于那些实现模板接口的用户来说，而不是那些创建Twig模板的人来说。

### 基础知识(Basics)

Twig使用一个名为环境(**environment**)的中心对象(类Twig\_Environment)。该类的实例用于存储配置和扩展，用于从文件系统或其他位置加载模板。

大多数应用程序将在应用程序初始化时创建一个Twig\_Environment对象，并将其用于加载模板。在某些情况下，如果使用不同的配置，那么有多个环境并排使用是非常有用的。

配置Twig到加载模板的最简单方法是这样的:

```php
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实例:

```php
$template = $twig->load('index.html');
```

要使用一些变量来呈现模板，请调用render()方法:

```php
echo $template->render(array('the' => 'variables', 'go' => 'here'));
```

> display()方法是直接输出模板的快捷方式。

您还可以加载并呈现模板一次搞定:

```php
echo $twig->render('index.html', array('the' => 'variables', 'go' => 'here'));
```

如果模板定义了块，则可以通过renderBlock()调用来单独呈现它们:

```php
echo $template->renderBlock('block_name', array('the' => 'variables', 'go' => 'here'));
```

### 环境选项(Environment Options)

当创建一个新的Twig\_Environment实例时，可以将一系列选项作为构造函数的第二个参数:

```php
$twig = new Twig_Environment($loader, array('debug' => true));
```

以下选项可供选择:

* debug 布尔类&#x578B;*(boolean)*

当设置为true时，生成的模板有一个\_\_toString()方法，您可以使用它来显示生成的节点(默认为false)。

* charset 字符串类型(string)(默认为utf-8)

用于生成模板的基础模板类。

* cache 字符串类型(string) 或 false

一个绝对路径，用于存储已编译的模板，或者是false来禁用缓存(这是默认的)。

* auto\_reload 布尔类&#x578B;*(boolean)*

当使用Twig进行开发时，每当源代码发生变化时重新编译模板是很有用的。如果您不为auto\_reload选项提供一个值，那么它将根据调试值自动确定。

* strict\_variables 布尔类&#x578B;*(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从文件系统加载模板。这个加载器可以在文件系统的文件夹中找到模板，并且是加载它们的首选方法:

```php
$loader = new Twig_Loader_Filesystem($templateDir);
```

它还可以在一系列目录中寻找模板:

```php
$loader = new Twig_Loader_Filesystem(array($templateDir1, $templateDir2));
```

有了这样的配置，Twig将首先在$ templateDir1中寻找模板，如果它们不存在，那么它就会在$ templateDir2中寻找它们。

您可以通过addPath()和prependPath()方法添加或prepend路径:

```php
$loader->addPath($templateDir3);
$loader->prependPath($templateDir4);
```

文件系统加载器还支持名称空间模板。这允许在有自己的模板路径的不同名称空间中对模板进行分组。

当使用setpath()、addPath()和prependPath()方法时，将名称空间指定为第二个参数(当未指定时，这些方法将在“main”命名空间上执行):

```php
$loader->addPath($templateDir, 'admin');
```

名称空间模板可以通过特殊的@ namespace\_name / template\_path符号来访问:

```php
$twig->render('@admin/index.html', array());
```

Twig\_Loader\_Filesystem支持绝对和相对路径。使用相对路径是首选的，因为它使缓存键独立于项目根目录(例如，它允许从构建服务器中缓存缓存，其中目录可能与生产服务器上使用的目录不同):

```php
$loader = new Twig_Loader_Filesystem('templates', getcwd().'/..');
```

> 当没有将根路径作为第二个参数传递时，Twig会使用getcwd()相对路径。

Twig\_Loader\_Array

Twig\_Loader\_Array从一个PHP数组加载一个模板。它传递了绑定到模板名称的字符串数组:

```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将模板加载到其他加载器:

```php
$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:

```php
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()方法:

```php
$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的所有核心特性:

* [Tags](https://twig.sensiolabs.org/doc/2.x/tags/index.html)
* [Filters](https://twig.sensiolabs.org/doc/2.x/filters/index.html)
* [Functions](https://twig.sensiolabs.org/doc/2.x/functions/index.html)
* [Tests](https://twig.sensiolabs.org/doc/2.x/tests/index.html)

#### 转义扩展(Escaper Extension)

转义扩展增加了自动输出转义到Twig。它定义了一个标签、autoescape和一个过滤器，raw。

在创建转义扩展时，您可以打开或关闭全局输出转义策略:

```php
$escaper = new Twig_Extension_Escaper('html');
$twig->addExtension($escaper);
```

如果设置为html，模板中的所有变量都可以通过(使用html转义策略)，除非使用raw过滤器:

```php
{{ article.to_html|raw }}
```

您还可以使用自动转义标签改变本地的转义模式:

```php
{% autoescape 'html' %}
    {{ var }}
    {{ var|raw }}      {# var won't be escaped #}
    {{ var|escape }}   {# var won't be double-escaped #}
{% endautoescape %}
```

> autoescape标签对包含的文件没有影响。

转义规则执行如下:

* 直接在模板中使用的文本(整数、布尔值、数组等)不会自动转义:

```php
{{ "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 #}
```

* 在打印之前，在其他过滤器被应用后，转义被应用:

```markup
{{ 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是安全的。

```markup
{% 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。这个类允许你列出一些标签、过滤器、属性和方法:

```php
$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构造函数的第一个参数:

```php
$sandbox = new Twig_Extension_Sandbox($policy);
$twig->addExtension($sandbox);
```

默认情况下，sandbox模式是禁用的，当使用sandbox标记包含不受信任的模板代码时，应该启用这个模式:

```markup
{% sandbox %}
    {% include 'user.html' %}
{% endsandbox %}
```

您可以将所有模板都通过true作为扩展构造函数的第二个参数:

```php
$sandbox = new Twig_Extension_Sandbox($policy, true);
```

#### 分析器扩展(Profiler Extension)

profiler扩展允许对Twig模板进行分析器;它应该只在您的开发机器上使用，因为它增加了一些开销:

```php
$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/)兼容的格式:

```php
$dumper = new Twig_Profiler_Dumper_Blackfire();
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
```

上传资料，以使其可视化(先创建一个[免费帐户](https://blackfire.io/signup)):

```php
blackfire --slot=7 upload /path/to/profile.prof
```

#### 优化器扩展(Optimizer Extension)

优化器扩展在编译之前优化节点树:

```php
$twig->addExtension(new Twig_Extension_Optimizer());
```

默认情况下，所有的优化都是打开的。您可以通过将它们传递给构造函数来选择要启用的函数:

```php
$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:当一个不允许的标记、过滤器或方法被调用在一个沙盒模板中时抛出。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://twig.shujuwajue.com/twig-2x/4-twig-for-kai-fa-zhe.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
