Smarty 模板引擎入门教程

目录

  1. 第一部分:什么是 Smarty?为什么要用它?

    • 1 定义与核心思想
    • 2 使用 Smarty 的好处
    • 3 谁适合学习 Smarty?(以及现代替代方案)
  2. 第二部分:环境准备与安装

    • 1 系统要求
    • 2 安装 Smarty(Composer 方式,最推荐)
    • 3 项目目录结构
  3. 第三部分:核心概念与基本使用

    • 1 模板文件
    • 2 PHP 脚本(分配变量)
    • 3 模板引擎(初始化与渲染)
    • 4 变量输出
    • 5 注释
    • 6 常用配置项
  4. 第四部分:Smarty 常用功能详解

    • 1 修饰器 - 格式化变量
    • 2 内建函数 - 流程控制
      • {if}...{/if} 条件判断
      • {foreach}...{/foreach} 数组循环
      • {section}...{/section} 数字循环(较少用)
    • 3 包含文件与继承
      • {include} 包含子模板
      • {extends}{block} 模板继承(高级功能)
  5. 第五部分:一个完整的实战案例

    • 1 需求分析
    • 2 项目结构
    • 3 编写 PHP 脚本
    • 4 编写模板文件
    • 5 运行效果
  6. 第六部分:总结与展望


第一部分:什么是 Smarty?为什么要用它?

1 定义与核心思想

Smarty 是一个用 PHP 编写的模板引擎,它的核心思想是 “关注点分离”(Separation of Concerns)

就是把 PHP 代码(业务逻辑)HTML 代码(页面展示) 分离开。

  • PHP 文件:负责处理数据、数据库查询、业务计算等“后台”工作。
  • 模板文件:负责展示数据、设计页面布局等“前台”工作,它看起来很像 HTML,但里面可以嵌入 Smarty 的特定标签。

2 使用 Smarty 的好处

  1. 代码清晰,易于维护:前端开发者可以专注于 HTML/CSS/JS,而不用担心 PHP 代码的复杂性,后端开发者则专注于业务逻辑,无需关心页面样式,修改页面布局时,只需修改 .tpl 文件,而不会触碰核心的 PHP 业务代码。
  2. 提升安全性:Smarty 默认会对所有输出到模板的变量进行 HTML 转义,可以有效防止 XSS 跨站脚本攻击,虽然可以关闭此功能,但默认开启是一个非常好的安全实践。
  3. 提高开发效率:模板引擎提供了很多便捷的语法(如循环、条件判断),让复杂的页面逻辑在模板中就能实现,减少了在 PHP 中拼接 HTML 字符串的繁琐工作。
  4. 可重用性:通过 {include} 和模板继承,可以轻松创建公共的头部、底部、导航栏等,并在多个页面中复用。

3 谁适合学习 Smarty?(以及现代替代方案)

适合场景

  • 学习模板引擎的基本概念和工作原理。
  • 维护一些使用 Smarty 构建的旧项目。
  • 在某些小型项目中,希望快速实现前后端分离。

现代替代方案: 在现代 PHP 开发中,随着 MVC 框架(如 Laravel, Symfony)的普及,人们更倾向于在控制器中直接传递数据给 Blade、Twig 等现代模板引擎,它们通常与框架深度集成,功能更强大,语法也更简洁。

Twig(Symfony 框架使用)是目前最流行的 PHP 模板引擎之一,其语法非常优雅,功能强大,但从学习角度看,Smarty 的概念与 Twig 高度相似,学懂了 Smarty,再学 Twig 会非常容易。


第二部分:环境准备与安装

1 系统要求

  • PHP 5.2+ (推荐 7.0+)
  • 一个 Web 服务器(如 Apache 或 Nginx)
  • Composer(PHP 依赖管理工具,强烈推荐)

2 安装 Smarty(Composer 方式,最推荐)

  1. 安装 Composer:如果你的系统还没有 Composer,请先从 getcomposer.org 下载并安装。

  2. 创建项目目录

    mkdir smarty_project
    cd smarty_project
  3. 使用 Composer 安装 Smarty: 在项目根目录下执行命令:

    composer require smarty/smarty

    执行后,你的项目目录下会出现一个 vendor 文件夹,里面包含了 Smarty 的所有源码。

3 项目目录结构

一个规范的 Smarty 项目目录结构如下:

smarty_project/
├── vendor/                 // Composer 自动生成的依赖包
│   └── smarty/
├── app/                    // 应用程序目录
│   ├── controllers/        // 控制器目录 (可选)
│   └── templates_c/        // Smarty 编译后的模板缓存目录 (重要!)
├── templates/              // 模板文件目录
│   ├── layouts/           // 布局模板
│   │   └── main.tpl
│   └── index.tpl          // 首页模板
├── index.php              // 入口文件
└── composer.json          // Composer 配置文件

注意

  • templates_c 目录必须存在,Web 服务器(如 Apache/Nginx 的运行用户)需要有写入权限,Smarty 会把模板文件编译成 PHP 代码存放在这里以提高性能。
  • templates 目录存放我们写的 .tpl 文件。

第三部分:核心概念与基本使用

1 模板文件

模板文件是纯文本文件,通常以 .tpl 为后缀,它包含 HTML 和 Smarty 标签。

示例 templates/index.tpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">我的第一个 Smarty 页面</title>
</head>
<body>
    <h1>欢迎来到 {$pageTitle}</h1>
    <p>今天是 {$currentDate}。</p>
</body>
</html>

{$pageTitle}{$currentDate} Smarty 的变量标签,里面的值将由 PHP 脚本传入。

2 PHP 脚本(分配变量)

PHP 脚本负责创建数据,并将其“分配”给 Smarty。

示例 index.php

<?php
// 1. 引入 Composer 的自动加载文件
require 'vendor/autoload.php';
// 2. 创建 Smarty 对象
$smarty = new Smarty();
// 3. 配置 Smarty 的目录路径
$smarty->setTemplateDir(__DIR__ . '/templates');      // 设置模板目录
$smarty->setCompileDir(__DIR__ . '/app/templates_c');  // 设置编译目录
$smarty->setCacheDir(__DIR__ . '/app/cache');         // 设置缓存目录 (可选)
// 4. 分配变量
$smarty->assign('pageTitle', 'Smarty 学习教程');
$smarty->assign('currentDate', date('Y-m-d H:i:s'));
// 5. 显示模板
$smarty->display('index.tpl');
?>

3 模板引擎(初始化与渲染)

上面的 PHP 脚本完成了三件事:

  1. 引入:通过 composer 的自动加载器加载 Smarty 类。
  2. 配置:告诉 Smarty 模板文件和编译文件分别放在哪里。
  3. 执行
    • assign():将 PHP 变量名和值传递给 Smarty。
    • display():加载指定的模板文件,用分配的变量替换模板中的标签,然后将最终生成的 HTML 输出到浏览器。

4 变量输出

  • 简单变量{$variableName}

    • {$pageTitle} 会输出 "Smarty 学习教程"。
  • 数组变量

    // PHP 中
    $user = ['name' => '张三', 'age' => 30];
    $smarty->assign('user', $user);
    // 模板中
    姓名: {$user.name} 或 {$user['name']} <br>
    年龄: {$user.age}
  • 对象属性

    // PHP 中
    class User {
        public $name = '李四';
    }
    $smarty->assign('user_obj', new User());
    // 模板中
    姓名: {$user_obj->name}

5 注释

Smarty 注释不会在最终的 HTML 源码中显示,非常安全。

{* 这是一个Smarty注释,前端用户看不到 *}

6 常用配置项

可以在创建 Smarty 对象后进行配置:

$smarty = new Smarty();
// 关闭缓存(开发时建议开启,方便调试)
$smarty->caching = false;
// 模板文件后缀
$smarty->template_ext = 'tpl';
// 是否检查模板文件是否被修改(开发时建议开启)
$smarty->compile_check = true;

第四部分:Smarty 常用功能详解

1 修饰器 - 格式化变量

修饰器用于格式化变量的输出,用 符号连接。

{$price|default:'0.00'} {* $price 未设置,则显示 '0.00' *}
{$longText|truncate:50} {* 截断长文本,只显示前50个字符 *}
{$name|upper}           {* 将 $name 转换为大写 *}
{$date|date_format:'%Y-%m-%d'} {* 格式化日期 *}

2 内建函数 - 流程控制

{if}...{/if} 条件判断

{if $user.age >= 18}
    <p>{$user.name} 已成年。</p>
{elseif $user.age > 0}
    <p>{$user.name} 是未成年。</p>
{else}
    <p>年龄信息未知。</p>
{/if}

{foreach}...{/foreach} 数组循环

这是最常用的循环方式。

<ul>
{foreach $products as $product}
    <li>
        <strong>{$product.name}</strong> - 价格: {$product.price} 元
    </li>
{/foreach}
</ul>

获取循环信息{$product} 是当前元素,你还可以使用 {$@key}{$@iteration} 来获取键和迭代次数。

{foreach $products as $key => $product}
    {if $@iteration is even}
        <li style="background-color: #f0f0f0;"> {* 偶数行高亮 *}
    {else}
        <li>
    {/if}
        ID: {$@key}, 名称: {$product.name}, 序号: {$@iteration}
    </li>
{/foreach}

{section}...{/section} 数字循环

这个函数用于循环一个固定范围的数字,现在较少使用,但了解一下也无妨。

{section name=i loop=5}
    <p>这是第 {$i.index + 1} 次循环。</p>
{/section}

3 包含文件与继承

{include} 包含子模板

用于将一个模板文件嵌入到另一个模板文件中,非常适合创建公共的头部、底部等。

templates/header.tpl:

<head>{$pageTitle|default:'默认标题'}</title>
</head>
<body>
    <header>网站头部导航</header>

templates/footer.tpl:

    <footer>网站底部信息 &copy; 2025</footer>
</body>
</html>

templates/index.tpl:

{include file='header.tpl'}
    <main>
        <h1>主页内容</h1>
        <p>这里是主页的主体内容。</p>
    </main>
{include file='footer.tpl'}

{extends}{block} 模板继承(高级功能)

这是更强大的复用机制,类似于面向对象中的继承。

  1. 创建一个父模板(布局模板)

    templates/layouts/main.tpl:

    <!DOCTYPE html>
    <html>
    <head>
        <title>{block name='title'}默认网站标题{/block}</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <header>网站头部</header>
        {block name='content'}
            <!-- 这是默认内容,如果子模板不覆盖,就会显示这个 -->
            <p>这是默认的页面内容。</p>
        {/block}
        <footer>网站底部</footer>
    </body>
    </html>
  2. 创建一个子模板,继承父模板

    templates/index.tpl:

    {extends 'layouts/main.tpl'}
    {block name='title'}
        首页 - 我的网站
    {/block}
    {block name='content'}
        <h1>欢迎来到首页!</h1>
        <p>这是首页特有的内容,它覆盖了父模板中的默认内容。</p>
    {/block}

    子模板通过 {extends} 指定父模板,然后通过 {block} 覆盖父模板中同名的块,这种方式让布局管理变得非常清晰和高效。


第五部分:一个完整的实战案例

1 需求分析

创建一个简单的文章列表页面,页面包含:

  • 一个公共的头部和底部。
  • 一个文章列表,每篇文章显示标题、作者和发布日期。
  • 使用模板继承来布局。

2 项目结构

沿用第二部分的目录结构。

smarty_project/
├── vendor/
├── app/
│   └── templates_c/
├── templates/
│   ├── layouts/
│   │   └── main.tpl
│   └── article_list.tpl
├── index.php
└── composer.json

3 编写 PHP 脚本 (index.php)

<?php
require 'vendor/autoload.php';
$smarty = new Smarty();
$smarty->setTemplateDir(__DIR__ . '/templates');
$smarty->setCompileDir(__DIR__ . '/app/templates_c');
// 1. 模拟从数据库获取文章数据
$articles = [
    [
        'id'      => 1,
        'title'   => 'Smarty 模板引擎入门指南',
        'author'  => '张三',
        'date'    => '2025-10-25'
    ],
    [
        'id'      => 2,
        'title'   => 'PHP 面向对象编程详解',
        'author'  => '李四',
        'date'    => '2025-10-24'
    ],
    [
        'id'      => 3,
        'title'   => '使用 Composer 管理项目依赖',
        'author'  => '王五',
        'date'    => '2025-10-23'
    ]
];
// 2. 分配变量给模板
$smarty->assign('pageTitle', '文章列表');
$smarty->assign('articles', $articles);
// 3. 显示模板
$smarty->display('article_list.tpl');
?>

4 编写模板文件

父模板 templates/layouts/main.tpl:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">{block name='page_title'}默认标题{/block}</title>
    <style>
        body { font-family: sans-serif; }
        header, footer { background: #333; color: white; text-align: center; padding: 10px; }
        article { border: 1px solid #ccc; margin: 10px; padding: 15px; border-radius: 5px; }
    </style>
</head>
<body>
    <header>我的博客网站</header>
    <main>
        {block name='content'}{/block}
    </main>
    <footer>&copy; 2025 All Rights Reserved.</footer>
</body>
</html>

子模板 templates/article_list.tpl:

{extends 'layouts/main.tpl'}
{* 覆盖父模板的标题块 *}
{block name='page_title'}
    {$pageTitle}
{/block}
{* 覆盖父模板的内容块 *}
{block name='content'}
    <h1>所有文章</h1>
    {foreach $articles as $article}
        <article>
            <h2><a href="article.php?id={$article.id}">{$article.title}</a></h2>
            <p>
                <small>作者: {$article.author} | 发布日期: {$article.date}</small>
            </p>
        </article>
    {/foreach}
{/block}

5 运行效果

将项目部署到你的 Web 服务器(如 Apache 的 htdocs 或 Nginx 的 html 目录),然后访问 index.php,你将看到一个样式良好的文章列表页面。


第六部分:总结与展望

恭喜!你已经完成了 Smarty 的入门学习,现在你应该掌握了:

  • Smarty 的核心思想和优势。
  • 如何安装和配置一个 Smarty 项目。
  • 如何在 PHP 和模板之间传递变量。
  • 如何使用 Smarty 的基本语法:变量、注释、修饰器。
  • 如何使用 {if}, {foreach} 进行逻辑控制。
  • 如何使用 {include}{extends} 实现模板的复用和继承。

下一步可以学习的内容

  • 缓存:Smarty 有强大的缓存功能,可以极大提高网站性能,学习如何开启和使用缓存。
  • 插件:你可以编写自己的修饰器或函数来扩展 Smarty 的功能。
  • 配置文件:学习如何使用外部配置文件来管理网站的全局变量。

虽然现代框架更多地使用 Twig 等新一代模板引擎,但 Smarty 所代表的 “模板与逻辑分离” 的思想是整个 Web 开发领域的重要基石,掌握它,不仅能让你轻松维护旧项目,更能让你深刻理解现代前端框架(如 Vue, React)中组件化思想的根源。