Twig
最后修改于 2025 年 2 月 16 日
Twig 教程展示了如何在 PHP 应用程序中使用 Twig 模板引擎来生成文档。
Twig
Twig 是一个 PHP 模板引擎。它由 Symfony 开发人员创建。Twig 文件的扩展名为 .html.twig
;它们是静态数据(如 HTML)和 Twig 构造的混合体。
Twig 使用双大括号分隔符 {{ }}
用于输出,使用大括号百分比分隔符 {% %}
用于逻辑。 {# #}
用于注释。
<ul> {% for word in words %} <li>{{ word }}</li> {% endfor %} </ul>
此代码是一个示例 Twig 语法。在此代码中,我们使用 for
标签来创建一个循环。
Twig 语法由标签、过滤器、函数、运算符和测试组成。
设置 Twig
首先,我们设置 Twig。
$ composer require twig/twig
我们使用 composer 安装 Twig。
$ mkdir templates
我们将模板文件放置在 template
目录中。
require __DIR__ . '/vendor/autoload.php';
我们需要将 autoload.php
文件添加到我们的脚本中。
模板引擎
模板引擎或模板处理器是一个旨在将模板与数据模型结合起来以生成文档的库。模板引擎通常用于生成大量电子邮件、源代码预处理或生成动态 HTML 页面。
我们创建一个模板引擎,在其中定义静态部分和动态部分。动态部分稍后将被数据替换。渲染函数随后会将模板与数据结合起来。
Twig 第一个例子
以下是 Twig 模板系统的一个简单演示。
<?php require __DIR__ . '/vendor/autoload.php'; use Twig\Environment; use Twig\Loader\FilesystemLoader; $loader = new FilesystemLoader(__DIR__ . '/templates'); $twig = new Environment($loader); echo $twig->render('first.html.twig', ['name' => 'John Doe', 'occupation' => 'gardener']);
我们使用 FilesystemLoader
从指定的目录加载模板。
echo $twig->render('first.html.twig', ['name' => 'John Doe', 'occupation' => 'gardener']);
输出使用 render
生成。它有两个参数:模板文件和数据。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <p> {{ name }} is a {{ occupation }} </p> </body> </html>
这是模板文件。变量使用 {{}}
语法输出。
$ php first.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <p> John Doe is a gardener </p> </body> </html>
Twig 过滤器
过滤器允许我们以各种方式修改数据。
<?php require __DIR__ . '/vendor/autoload.php'; use Twig\Environment; use Twig\Loader\FilesystemLoader; $loader = new FilesystemLoader(__DIR__ . '/templates'); $twig = new Environment($loader); $words = ['sky', 'mountain', 'falcon', 'forest', 'rock', 'blue']; $sentence = 'today is a windy day'; echo $twig->render('filters.html.twig', ['words' => $words, 'sentence' => $sentence]);
在这个例子中,我们有一个数组和一个字符串作为模板数据。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Filters</title> </head> <body> <p> The array has {{ words | length }} elements </p> <p> Joined array elements: {{ words | join(',') }} </p> <p> {{ sentence | title }} </p> </body> </html>
过滤器使用 |
字符应用。该示例使用 length
计数单词,使用 join
连接数组元素,并使用 title
修改字符。
Twig 自定义过滤器
我们可以使用 Twig_Filter
创建自定义过滤器。
<?php require __DIR__ . '/vendor/autoload.php'; use Twig\Environment; use Twig\Loader\FilesystemLoader; $loader = new FilesystemLoader(__DIR__ . '/templates'); $twig = new Environment($loader); $twig->addFilter(new Twig_Filter('accFirst', 'accFirst')); $sentence = 'šumivé víno'; echo $twig->render('customfilter.html.twig', ['sentence' => $sentence]); function accFirst($value, $encoding = 'UTF8') { $strlen = mb_strlen($value, $encoding); $firstChar = mb_substr($value, 0, 1, $encoding); $rest = mb_substr($value, 1, $strlen - 1, $encoding); return mb_strtoupper($firstChar, $encoding) . $rest; }
我们添加了一个名为 accFirst
的新过滤器。它仅修改第一个字母,并且还可以处理重音符号。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Custom filter</title> </head> <body> <p> {{ sentence | accFirst }} </p> </body> </html>
这是模板文件,它使用自定义的 accFirst
过滤器。
Twig 循环
要创建循环,我们使用 for
标签。
<?php require __DIR__ . '/vendor/autoload.php'; use Twig\Environment; use Twig\Loader\FilesystemLoader; $loader = new FilesystemLoader(__DIR__ . '/templates'); $twig = new Environment($loader); $words = ['sky', 'mountain', 'falcon', 'forest', 'rock', 'blue', 'solid', 'book', 'tree']; echo $twig->render('words.html.twig', ['words' => $words]);
我们将循环一个单词数组。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Words</title> </head> <body> <ul> {% for word in words %} <li>{{ word }}</li> {% endfor %} </ul> <ul> {% for word in words|slice(2, 4) %} <li>{{ word }}</li> {% endfor %} </ul> </body> </html>
在模板文件中,我们循环遍历 words
数组并生成一个 HTML 列表。使用 slice
过滤器,我们可以循环遍历数组的一部分。
Twig 使用 if & else 循环
我们可以将 for
标签与 if
标签和 else
标签结合使用。
<?php require __DIR__ . '/vendor/autoload.php'; use Twig\Environment; use Twig\Loader\FilesystemLoader; $loader = new FilesystemLoader(__DIR__ . '/templates'); $twig = new Environment($loader); $users = [ ['name' => 'John Doe', 'active' => false], ['name' => 'Lucy Smith', 'active' => false], ['name' => 'Peter Holcombe', 'active' => false], ['name' => 'Barry Collins', 'active' => false] ]; echo $twig->render('activeusers.html.twig', ['users' => $users]);
我们将一个用户数组发送到模板文件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <p>Active users</p> <ul> {% for user in users if user.active %} <li>{{ user.name }}</li> {% else %} <li>No users found</li> {% endfor %} </ul> </body> </html>
如果 user.active
属性为 true,我们输出用户的姓名。当没有活动用户时,会显示 else
标签的输出。
Twig set 标签
set
标签允许在模板内为变量设置一个值。
$words = ['sky', 'mountain', 'falcon', 'forest', 'rock', 'blue', 'solid', 'book', 'tree']; echo $twig->render('test.html.twig', ['words' => $words]);
我们有一系列单词。
{% set sorted = words | sort %} <ul> {% for word in sorted %} <li>{{ word }}</li> {% endfor %} </ul>
我们使用 sort
过滤器对数组进行排序,并将排序后的数组使用 set
分配给 sorted
变量。
Twig verbatim 标签
verbatim
将部分标记为不应解析的原始文本。
{% verbatim %} <ul> {% for word in words %} <li>{{ word }}</li> {% endfor %} </ul> {% endverbatim %}
例如,如果我们有一个解释某些 Twig 标签的教程,我们将不需要解析演示文稿的一部分。
Twig format 过滤器
format
过滤器通过替换占位符来格式化给定的字符串。它类似于 sprintf
函数。
$name = "John Doe"; $age = 34; echo $twig->render('formatfil.html.twig', ['name' => $name, 'age' => $age]);
我们将两个变量发送到模板。
{{ "%s is %d years old" | format(name, age) }}
我们使用 format
构建字符串。
Twig date 函数
date
函数将一个参数转换为日期,以允许日期比较。
$user = ['name' => 'John Doe', 'created_at' => '2011/11/10']; echo $twig->render('datefun.html.twig', ['user' => $user]);
用户数组有一个 created_at
键。
{% if date(user.created_at) < date('-5years') %} <p>{{ user.name }} is a senior user</p> {% endif %}
在模板中,我们比较两个日期。
Twig 自动转义
Twig 自动转义某些字符,例如 < 或 >。
$twig = new Environment($loader, [ 'autoescape' => false ]);
可以使用 autoescape
选项关闭自动转义。
$data = "<script src='http::/example.com/nastyscript.js'></script>"; echo $twig->render('autoescape.html.twig', ['data' => $data]);
用户可能会向应用程序添加潜在的危险输入。包含未知 JS 文件可以通过自动转义来防止。
<p> The data is {{ data }} </p> <p> The data is {{ data | raw }} </p>
如果启用了自动转义,我们可以使用 raw
过滤器显示原始输入。
<p> The data is <script src='http::/example.com/nastyscript.js'></script> </p> <p> The data is <script src='http::/example.com/nastyscript.js'></script> </p>
此部分输出显示了字符的转义方式。
Twig 测试
Twig 测试允许测试数据。测试使用 is
运算符应用。
$words = ['', null, 'rock', ' ', 'forest']; echo $twig->render('tests.html.twig', ['words' => $words]);
我们有一个单词数组,其中包含空元素和空白元素。
<ul> {% for word in words %} {% if word is null %} <p>null element</p> {% elseif word | trim is empty %} <p>Empty element</p> {% else %} <li>{{ word }}</li> {% endif %} {% endfor %} </ul>
为了处理空元素和空白元素,Twig 有 empty
和 null
测试。
Twig 继承
Twig 的模板继承是一个强大的功能,它可以消除重复并促进维护。
<?php require __DIR__ . '/vendor/autoload.php'; use Twig\Environment; use Twig\Loader\FilesystemLoader; $loader = new FilesystemLoader(__DIR__ . '/templates'); $twig = new Environment($loader); echo $twig->render('derived.html.twig');
这是 inheritance.php
文件。它呈现 derived.html.twig
,该文件从 base.html.twig
扩展而来。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{% block title %}{% endblock %}</title> </head> <body> {% block body %}{% endblock %} </body> </html>
基本布局定义了两个将被子项替换的块:title
和 body
。
{% extends 'base.html.twig' %} {% block title %}Some title{% endblock %} {% block body %} The body contents {% endblock %}
派生子模板使用 extends
关键字从基本模板继承。这两个块定义了自定义文本。
$ php inheritance.php <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Some title</title> </head> <body> The body contents </body> </html>
Symfony 示例
Twig 是 Symfony 框架不可或缺的一部分。下一个例子展示了在 Symfony 骨架应用程序中使用 Twig 的步骤。
$ composer create-project symfony/skeleton simple $ cd simple
我们创建一个新的 Symfony 骨架应用程序并移动到项目目录。
$ composer require server --dev
我们包含开发服务器。
$ composer require maker annotations twig
我们包含一些基本的 Symfony 组件,包括 Twig。
$ php bin/console make:controller HomeController
我们创建一个 home 控制器。
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; class HomeController extends AbstractController { /** * @Route("/home", name="home") */ public function index() { $words = ['sky', 'blue', 'cloud', 'symfony', 'forest']; return $this->render('home/index.html.twig', [ 'words' => $words ]); } }
在 home 控制器中,我们呈现 index.html.twig
模板,并将 $words
数组传递给它进行处理。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{% block title %}Welcome!{% endblock %}</title> {% block stylesheets %}{% endblock %} </head> <body> {% block body %}{% endblock %} {% block javascripts %}{% endblock %} </body> </html>
这是基本布局页面。
{% extends 'base.html.twig' %} {% block title %}Home page{% endblock %} {% block body %} <h2>List of words</h2> <ul> {% for word in words %} <li>{{ word }}</li> {% endfor %} </ul> {% endblock %}
这是主页模板。它使用 for
标签遍历单词,并将它们输出到无序列表中。
$ php bin/console server:run
我们启动服务器。
我们导航到 https://:8000/home
以查看结果。
来源
在本文中,我们使用 Twig 从模板和数据生成文档。我们介绍了 Twig 标签、过滤器、测试和继承。我们在 Symfony 应用程序中展示了 Twig。
作者
列出所有 PHP 教程。