Twig基础 #
一、Twig概述 #
1.1 什么是Twig #
Twig是Symfony默认的模板引擎,提供简洁、安全的模板语法。
text
┌─────────────────────────────────────────────────────┐
│ Twig 特点 │
├─────────────────────────────────────────────────────┤
│ • 简洁语法:{{ }} 输出,{% %} 逻辑,{# #} 注释 │
│ • 安全性:自动转义,沙箱模式 │
│ • 可扩展:自定义过滤器、函数、标签 │
│ • 高性能:编译缓存 │
│ • 面向对象:模板继承、区块覆盖 │
└─────────────────────────────────────────────────────┘
1.2 基本语法 #
twig
{# 这是注释 #}
{# 输出变量 #}
{{ name }}
{# 逻辑控制 #}
{% if user.active %}
<p>用户已激活</p>
{% endif %}
{# 循环 #}
{% for item in items %}
<li>{{ item.name }}</li>
{% endfor %}
二、变量输出 #
2.1 输出变量 #
twig
{# 简单变量 #}
{{ name }}
{{ user.name }}
{{ user['name'] }}
{# 对象属性 #}
{{ user.getName() }}
{{ user.name }}
{# 数组元素 #}
{{ users[0] }}
{{ users.0 }}
{# 嵌套访问 #}
{{ user.address.city }}
{{ order.items[0].product.name }}
2.2 输出过滤器 #
twig
{# 转义 #}
{{ content|e }}
{{ content|e('html') }}
{# 原始输出(不转义) #}
{{ html|raw }}
{# 默认值 #}
{{ user.name|default('匿名用户') }}
{# 长度 #}
{{ items|length }}
{# 类型转换 #}
{{ value|string }}
{{ value|integer }}
{{ value|float }}
{{ value|boolean }}
三、文本处理 #
3.1 字符串过滤器 #
twig
{# 大小写转换 #}
{{ name|upper }}
{{ name|lower }}
{{ name|capitalize }}
{{ name|title }}
{# 去除空白 #}
{{ text|trim }}
{{ text|trim('-') }}
{{ text|trim(side='left') }}
{# 截取 #}
{{ text|slice(0, 10) }}
{{ text|slice(0, 10) ~ '...' }}
{# 字符串操作 #}
{{ text|replace({'foo': 'bar'}) }}
{{ text|split(',') }}
{{ text|split('', 3) }}
{{ text|first }}
{{ text|last }}
{# 编码 #}
{{ url|url_encode }}
{{ text|json_encode }}
{{ text|html_encode }}
3.2 格式化 #
twig
{# 字符串格式化 #}
{{ "Hello, %s!"|format(name) }}
{{ "%s has %d items"|format(user.name, count) }}
{# 数字格式化 #}
{{ price|number_format }}
{{ price|number_format(2) }}
{{ price|number_format(2, ',', '.') }}
{# 日期格式化 #}
{{ date|date }}
{{ date|date('Y-m-d') }}
{{ date|date('Y-m-d H:i:s') }}
{{ date|date('Y年m月d日') }}
{# 相对时间 #}
{{ date|ago }}
3.3 文本处理示例 #
twig
{# 标题处理 #}
<h1>{{ article.title|capitalize }}</h1>
{# 摘要截取 #}
<p>{{ article.content|striptags|slice(0, 200) }}...</p>
{# 价格显示 #}
<span class="price">¥{{ product.price|number_format(2) }}</span>
{# 日期显示 #}
<time>{{ article.createdAt|date('Y-m-d H:i') }}</time>
{# URL友好化 #}
<a href="/article/{{ article.title|slug }}">{{ article.title }}</a>
四、控制结构 #
4.1 条件判断 #
twig
{# if语句 #}
{% if user.active %}
<p>用户已激活</p>
{% endif %}
{# if-else #}
{% if user.role == 'admin' %}
<p>管理员</p>
{% else %}
<p>普通用户</p>
{% endif %}
{# if-elseif-else #}
{% if score >= 90 %}
<p>优秀</p>
{% elseif score >= 80 %}
<p>良好</p>
{% elseif score >= 60 %}
<p>及格</p>
{% else %}
<p>不及格</p>
{% endif %}
{# 逻辑运算 #}
{% if user.active and user.verified %}
<p>活跃且已验证</p>
{% endif %}
{% if user.role == 'admin' or user.role == 'super_admin' %}
<p>管理员权限</p>
{% endif %}
{% if not user.banned %}
<p>用户正常</p>
{% endif %}
{# in运算符 #}
{% if user.role in ['admin', 'editor'] %}
<p>有编辑权限</p>
{% endif %}
{# 测试运算符 #}
{% if user.name is defined %}
<p>{{ user.name }}</p>
{% endif %}
{% if user is null %}
<p>用户不存在</p>
{% endif %}
{% if items is empty %}
<p>暂无数据</p>
{% endif %}
{% if number is even %}
<p>偶数</p>
{% endif %}
{% if number is odd %}
<p>奇数</p>
{% endif %}
4.2 循环 #
twig
{# 遍历数组 #}
<ul>
{% for user in users %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
{# 遍历关联数组 #}
<dl>
{% for key, value in config %}
<dt>{{ key }}</dt>
<dd>{{ value }}</dd>
{% endfor %}
</dl>
{# 循环变量 #}
<table>
{% for item in items %}
<tr class="{{ loop.index is odd ? 'odd' : 'even' }}">
<td>{{ loop.index }}</td>
<td>{{ item.name }}</td>
</tr>
{% endfor %}
</table>
{# loop变量属性 #}
loop.index {# 当前索引(从1开始) #}
loop.index0 {# 当前索引(从0开始) #}
loop.revindex {# 倒序索引(从1开始) #}
loop.revindex0 {# 倒序索引(从0开始) #}
loop.first {# 是否第一个 #}
loop.last {# 是否最后一个 #}
loop.length {# 总数量 #}
loop.parent {# 父循环 #}
{# else分支 #}
<ul>
{% for user in users %}
<li>{{ user.name }}</li>
{% else %}
<li>暂无用户</li>
{% endfor %}
</ul>
{# 循环控制 #}
{% for i in 1..10 %}
{% if i > 5 %}
{% break %}
{% endif %}
<p>{{ i }}</p>
{% endfor %}
{% for i in 1..10 %}
{% if i is even %}
{% continue %}
{% endif %}
<p>{{ i }}</p>
{% endfor %}
{# 范围循环 #}
{% for i in 0..10 %}
{{ i }}
{% endfor %}
{% for i in 'a'..'z' %}
{{ i }}
{% endfor %}
{# 步长循环 #}
{% for i in 0..10|step(2) %}
{{ i }}
{% endfor %}
五、数组处理 #
5.1 数组过滤器 #
twig
{# 排序 #}
{% for item in items|sort %}
{{ item }}
{% endfor %}
{# 反转 #}
{% for item in items|reverse %}
{{ item }}
{% endfor %}
{# 合并 #}
{% set all = items1|merge(items2) %}
{# 键名 #}
{% for key in items|keys %}
{{ key }}
{% endfor %}
{# 列取值 #}
{% for name in users|column('name') %}
{{ name }}
{% endfor %}
{# 过滤 #}
{% for user in users|filter(u => u.active) %}
{{ user.name }}
{% endfor %}
{# 映射 #}
{% for name in users|map(u => u.name|upper) %}
{{ name }}
{% endfor %}
{# 去重 #}
{% for tag in tags|unique %}
{{ tag }}
{% endfor %}
{# 批量处理 #}
{% for row in items|batch(3) %}
<div class="row">
{% for item in row %}
<div class="col">{{ item }}</div>
{% endfor %}
</div>
{% endfor %}
5.2 数组操作示例 #
twig
{# 用户列表 #}
<table>
<thead>
<tr>
<th>#</th>
<th>姓名</th>
<th>邮箱</th>
<th>状态</th>
</tr>
</thead>
<tbody>
{% for user in users|sort((a, b) => a.name <=> b.name) %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.active ? '活跃' : '禁用' }}</td>
</tr>
{% else %}
<tr>
<td colspan="4">暂无用户</td>
</tr>
{% endfor %}
</tbody>
</table>
{# 分组显示 #}
{% for row in products|batch(4) %}
<div class="row">
{% for product in row %}
<div class="col-md-3">
<div class="card">
<img src="{{ product.image }}">
<h5>{{ product.name }}</h5>
<p>¥{{ product.price|number_format(2) }}</p>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
六、变量操作 #
6.1 变量定义 #
twig
{# set定义变量 #}
{% set name = 'John' %}
{% set age = 25 %}
{% set active = true %}
{# 定义数组 #}
{% set colors = ['red', 'green', 'blue'] %}
{% set user = {'name': 'John', 'age': 25} %}
{# 定义多行文本 #}
{% set content %}
<div class="content">
<p>多行内容</p>
</div>
{% endset %}
{# 使用变量 #}
<p>{{ name }}</p>
<p>{{ colors|join(', ') }}</p>
{{ content }}
6.2 变量作用域 #
twig
{# 全局变量 #}
{% set global = 'global' %}
{% for i in 1..3 %}
{# 循环内可访问全局变量 #}
{{ global }}
{# 循环内变量外部不可访问 #}
{% set local = 'local' ~ i %}
{% endfor %}
{# local变量这里不可访问 #}
{# 使用with创建作用域 #}
{% with %}
{% set temp = 'temporary' %}
{{ temp }}
{% endwith %}
{# temp变量这里不可访问 #}
七、包含和导入 #
7.1 include包含 #
twig
{# 包含模板 #}
{{ include('partials/header.html.twig') }}
{# 传递变量 #}
{{ include('partials/user_card.html.twig', {user: user}) }}
{# 传递多个变量 #}
{{ include('partials/product.html.twig', {
product: product,
showPrice: true,
showStock: false
}) }}
{# 条件包含 #}
{% if user %}
{{ include('partials/user_panel.html.twig') }}
{% else %}
{{ include('partials/login_panel.html.twig') }}
{% endif %}
{# 忽略错误 #}
{{ include('optional/template.html.twig', ignore_missing = true) }}
7.2 模板片段 #
twig
{# 定义片段 #}
{# templates/partials/cards.html.twig #}
{% card(title, content) %}
<div class="card">
<div class="card-header">{{ title }}</div>
<div class="card-body">{{ content }}</div>
</div>
{% endcard %}
{# 使用片段 #}
{% from 'partials/cards.html.twig' import card %}
{{ card('标题', '内容') }}
八、URL和路径 #
8.1 生成URL #
twig
{# 相对路径 #}
<a href="{{ path('app_home') }}">首页</a>
{# 带参数 #}
<a href="{{ path('app_user_show', {id: user.id}) }}">查看用户</a>
{# 绝对URL #}
<a href="{{ url('app_home') }}">首页</a>
{# 检查路由 #}
{% if path('app_admin_dashboard') is defined %}
<a href="{{ path('app_admin_dashboard') }}">管理后台</a>
{% endif %}
8.2 资源路径 #
twig
{# 静态资源 #}
<link rel="stylesheet" href="{{ asset('css/style.css') }}">
<script src="{{ asset('js/app.js') }}"></script>
<img src="{{ asset('images/logo.png') }}" alt="Logo">
{# 绝对路径资源 #}
<img src="{{ absolute_url(asset('images/logo.png')) }}">
{# 版本化资源 #}
<link rel="stylesheet" href="{{ asset('css/style.css', version='1.0.0') }}">
九、安全输出 #
9.1 自动转义 #
twig
{# 默认自动转义HTML #}
{{ content }} {# 自动转义 #}
{# 指定转义策略 #}
{{ content|e('html') }}
{{ content|e('js') }}
{{ content|e('css') }}
{{ content|e('url') }}
{# 不转义 #}
{{ trusted_html|raw }}
{# 关闭自动转义 #}
{% autoescape false %}
{{ content }}
{% endautoescape %}
{# 开启自动转义 #}
{% autoescape 'html' %}
{{ content }}
{% endautoescape %}
9.2 安全示例 #
twig
{# 用户输入内容 #}
<div class="content">
{{ userComment|e }}
</div>
{# 富文本(确保已过滤) #}
<div class="article">
{{ article.content|raw }}
</div>
{# JSON数据 #}
<script>
var userData = {{ user|json_encode|raw }};
</script>
{# 属性值 #}
<div class="user" data-name="{{ user.name|e('html_attr') }}">
{{ user.name }}
</div>
十、总结 #
本章学习了:
- Twig基本语法
- 变量输出和过滤器
- 文本处理
- 控制结构(条件、循环)
- 数组处理
- 变量定义和作用域
- 模板包含
- URL生成
- 安全输出
下一章将学习 模板继承。
最后更新:2026-03-28