您现在的位置: 365建站网 > 365文章 > PHP 编程 Smarty 怎么学?定界符冲突、编译缓存与插件写法

PHP 编程 Smarty 怎么学?定界符冲突、编译缓存与插件写法

文章来源:365jz.com 点击数:12 更新时间:2025-06-04 04:40

Smarty 是国内上一代 PHP 项目里最常见的模板引擎,Discuz、很多 CMS 早期都用过它的思路。今天接手老项目时最常问的是“定界符怎么改”“{if} 报语法错误”“模板改了不生效”。本文按“最小可运行 → 语法 → 编译缓存 → 常见坑”整理。

Smarty 模板引擎 入门语法与定界符

一、最小可运行示例

用 Composer 安装新版(Smarty 4/5):

composer require smarty/smarty
<?php
require 'vendor/autoload.php';

$smarty = new Smarty();
$smarty->setTemplateDir('templates/');   // .tpl 存放目录
$smarty->setCompileDir('templates_c/');  // 编译缓存
$smarty->setCacheDir('cache/');          // 可选:结果缓存

$smarty->assign('title', '365建站网');
$smarty->assign('list', [
    ['id'=>1,'name'=>'iPhone 15','price'=>5999],
    ['id'=>2,'name'=>'小米 14','price'=>3999],
]);
$smarty->display('index.tpl');

模板 templates/index.tpl:

<h1>{$title}</h1>
<ul>
{foreach $list as $item}
  <li>{$item.name} - {$item.price|number_format} 元</li>
{/foreach}
</ul>

三个目录都必须可写,否则报 “the $compile_dir ... is not writable”。Linux 下把属主改成 Web 用户(www-data)而不是给 777。

二、变量、修饰符与函数

  • 数组/对象取值:{$user.name}、{$arr['key']}、{$obj->method()}。
  • 修饰符(filter)用竖链接力:{$name|escape:'html'|truncate:20:'…'}。默认输出的转义函数由 $escape_html / 旧版 escape_html 策略决定,Smarty 3 起推荐显式写 |escape} 防 XSS。
  • 条件:{if $count > 10}...{elseif}...{/if};循环:{foreach}、{section}(老写法);包含:{include file="header.tpl"}。
  • PHP 官方手册式的“变量修饰符列表”可以查 Smarty 文档中的 modifiers 章节;常用的有 upper / lower / capitalize / nl2br / date_format / regex_replace / default。

三、定界符冲突(最常见的报错)

模板里如果写了 JS 模板字符串 ${var} 或 Angular/Vue 的 {{msg}},Smarty 会把它们当自己的语法解析,直接抛 “unrecognized tag”。两种解法:

// 1) 改成花括号定界(Smarty 3+ 支持)
$smarty->left_delimiter  = '{';
$smarty->right_delimiter = '}';
// 模板里写 {if $a}...{/if}

// 2) 或用自定义定界符避开
$smarty->left_delimiter  = '<{';
$smarty->right_delimiter = '}>';

需要局部屏蔽时用 {literal}...{/literal} 把一段 JS/CSS 包起来,里面的 { 不会被解析。

四、编译缓存与“改了不生效”

Smarty 把 .tpl 编译成 PHP 文件存进 templates_c,靠时间戳判断是否重新编译。改模板不生效通常有三个原因:

  • force_compile 与 check templates 设置:调试期设 $smarty->force_compile = true;(会拖慢),上线关掉;$smarty->compile_check = true; 是默认值,被人为关掉就不会自动重编。
  • 结果缓存 cache:调用了 $smarty->caching = 1; 且设了 cache_lifetime,页面内容会走缓存。清法:删 cache/ 目录,或 $smarty->clearAllCache();。
  • OPcache 缓存了编译产物:PHP 侧 opcache.revalidate_freq 较大时会延迟感知,调试期设 0 或 systemctl reload php-fpm。

Smarty 4 起不推荐用 clear_compile 做长期策略,生产应依赖时间戳检查。

五、PHP 代码能不能写进模板

Smarty 3 默认禁用 {php} 标签,需要显式开启:

$smarty->security = false;                 // 或配置 $smarty->allow_php_tag = true(视版本)

但即便能开,也不建议:模板里塞 PHP 逻辑等于放弃模板引擎的价值。正确做法是把计算放到 PHP 侧,用 assign 传结果,或者写自定义函数/插件:

function smarty_function_money($params, $template) {
    return number_format((float)$params['value'] / 100, 2);
}
// 模板里:{money value=$item.price}

Smarty 的插件按命名约定自动加载(smarty_function_xxx、smarty_modifier_xxx、smarty_block_xxx),放到 plugins_dir 即可。

六、安全配置

如果模板来自不可信来源(比如允许用户上传模板),必须开安全模式:

  • $smarty->security = true;,并配置 $secure_dir(限定模板目录)、$trusted_dir;
  • 限制可用的 PHP 函数与修饰符:$smarty->security_settings['PHP_TAGS'] = false;、MODIFIER_FUNCS 白名单;
  • 输出侧务必 escape,模板引擎本身不会自动防 XSS。

七、常见问题 FAQ

问:Smarty 现在还值得学吗?
答:新项目更常用 Laravel Blade、Twig 或直接 PHP 模板;但Smarty 在 Discuz、ECShop、老 CRM 里存量巨大,接手旧系统时属于必备知识。

问:和 Blade/Twig 的核心差异?
答:Smarty 用独立语法、插件目录约定、编译成 PHP 文件;Blade 直接编译为 PHP 并支持原生 PHP 片段,Twig 是沙箱化的严格语法。概念(模板继承、区块、过滤器)三家是相通的。

问:怎么在模板里访问全局变量?
答:Smarty 4 需要显式 $smarty->assign('g', $GLOBALS['g']),或用 {* $smarty.session.xxx *} 之类的保留变量($smarty.get/post/session/server/config)。

要点回顾:目录可写、定界符避开 JS、缓存三处分别清、模板里不写 PHP。把这四条记住,Smarty 的老项目就能顺畅维护。

生产内容,同时打通搜索引擎(SEO)与AI搜索引擎(GEO)流量入口的软件! 点击进入365建站器 »