Smarty常用自定义函数扩展实现:中文截取、UBB转HTML与Unescape解码

Chloe
Chloe
发布时间:2026-10-16| 4人浏览过
原创

在使用 Smarty 进行 Web 开发时,经常需要处理中文字符截断保持完整、UBB 标签转 HTML 显示以及 URL 编码解码等问题。通过编写自定义修饰符(Modifier)函数,可以显著提升模板页面的整洁度和数据处理能力。本文将逐一解析这三个核心扩展功能的实现原理与代码结构。

实现中文字符串安全截断

在展示摘要或列表内容时,直接截断字符串容易导致乱码,尤其是涉及多字节字符集(如 GBK 或 UTF-8)时。以下函数 smarty_modifier_cn_truncate 能够智能识别字符边界,确保截取后的字符串不乱码,同时支持保留首尾样式参数。

  1. 初始化与长度计算:输入字符串 $string 和目标长度 $strlen。为了兼容不同编码下的字节数,先将目标长度乘以 2(针对部分双字节逻辑进行调整),并去除首尾空格。
  2. 短文本直接返回:如果原字符串长度小于等于设定的最大长度,则直接返回原文,无需截取。
  3. 提取纯文本内容:使用 strip_tags() 去除原有 HTML 标签,得到纯净文本 $str。
  4. 字节边界检测:遍历指定长度的字节,利用 ord() 检查 ASCII 值是否大于 0xa0(通常是多字节字符标识)。若发现单数值的字节被切断,自动调整截取长度以保证完整性。
  5. 执行截取与追加省略号:根据调整后的长度截取子串,并在末尾添加省略号 $etc。
  6. 可选:保留原始样式:当 $keep_first_style 为真且包含包裹标签时,尝试定位起始和结束位置,重新拼接包含样式的最终字符串。注意此处使用了正则匹配,需确保源字符串符合预期结构。
代码如下:
function smarty_modifier_cn_truncate($string, $strlen = 20, $etc = '...',
    $keep_first_style = false)
{
    $strlen = $strlen*2;
    $string = trim($string);
    if ( strlen($string) <= $strlen ) {
        return $string;
    }
    $str = strip_tags($string);
    $j = 0;
    for($i=0;$i<$strlen;$i++) {
        if(ord(substr($str,$i,1))>0xa0) $j++;
    }
    if($j%2!=0) $strlen++;
    $rstr=substr($str,0,$strlen);
    if (strlen($str)>$strlen ) {$rstr .= $etc;}
    
    // 可选:尝试保留外部样式标签
    if ( $keep_first_style == true && ereg('^<(.*)>$',$string) ) {
        if ( strlen($str) <= $strlen ) {
            return $string;
        }
        $start_pos = strpos($string,substr($str,0,4));
        $end_pos = strpos($string,substr($str,-4));
        $end_pos = $end_pos+4;
        $rstr = substr($string,0,$start_pos) . $rstr . substr($string,$end_pos,strlen($string));
    }
    return $rstr;
}

将 UBB 代码转换为 HTML 标签

许多旧式论坛系统使用 UBB 标签(如 [b], [img])存储用户输入。该扩展函数 smarty_modifier_ubb 定义了一系列映射规则,将这些自定义标签批量替换为标准 HTML 元素,便于现代浏览器渲染和 CSS 控制。

  1. 定义映射数组:构建二维关联数组 $ubbs,键名为标签类型(如 quote, b, img, url 等),值为正则表达式模式及其对应的 HTML 替换字符串。
  2. 特殊符号处理:优先将通用列表符号 [*] 替换为 <li>,以便统一后续的列表处理逻辑。
  3. 循环替换执行:遍历所有定义的规则,调用辅助函数 ubb_replace 对正文进行全局正则替换。此过程会持续运行直到某次替换没有产生变化为止,以应对嵌套或复杂情况。
代码如下:
function smarty_modifier_ubb($str) {
    // 定义各类 UBB 标签到 HTML 的映射规则
    $ubbs['quote'][0] = '/\[quote\](.*?)\[\/quote\]/s';
    $ubbs['quote'][1] = '<blockquote>引用:<hr size=1>\1<hr size=1></blockquote>';
    $ubbs['b'][0] = '/\[b\](.*?)\[\/b\]/s';
    $ubbs['b'][1] = '<b>\1</b>';
    $ubbs['i'][0] = '/\[i\](.*?)\[\/i\]/s';
    $ubbs['i'][1] = '<i>\1</i>';
    // ... (此处省略其他常见标签如u, li, color等映射定义) ...
    $ubbs['img'][0] = '/\[img\](.*?)\[\/img\]/s';
    $ubbs['img'][1] = '<img border="0" src="\1">';
    $ubbs['url'][0] = '/\[url\](.*?)\[\/url\]/s';
    $ubbs['url'][1] = '<a href="\1" target="_blank">\1</a>';
    $ubbs['email'][0] = '/\[email=([^\]]+)\](.*?)\[\/email\]/s';
    $ubbs['email'][1] = '<a href="mailto:\2">\2</a>';
    // ... (更多图片、颜色、字体大小等高级映射逻辑) ...

    // 处理通用列表项符号
    $str = str_replace('[*]','<li>',$str);

    // 依次应用所有正则替换
    foreach ($ubbs as $ubb){
        $str = ubb_replace($ubb[0],$ubb[1],$str);
    }
    return $str;
}

// 辅助函数:执行多次替换直至稳定
function ubb_replace($pattern,$replacement,$str){
    do {
        $str_ret = $str;
        $str = preg_replace($pattern,$replacement,$str);
    }while($$str); // 注意:此处原代码写法可能存在变量语法歧义,建议在实际生产环境中确认变量作用域
    return $str_ret;
}

解析 URL 编码字符串 (Unescape)

在前端向后端传输数据时,中文字符常被编码为 Unicode 形式(如 %uXXXX)。此函数 smarty_modifier_unescape 专门用于将这类经过双重编码或特定格式的字符串还原为可读文本,主要适配 GB2312 等旧式编码环境,但在处理 UCS-2 序列时同样有效。

  1. 初步解码:首先使用 rawurldecode() 进行标准的 URL 解码,消除百分号转义符。
  2. 正则分离:使用正则可以区分出普通的非百分号字符块和特殊的 Unicode 编码块 (?:%u.{4})。
  3. 逐个转换 Unicode:遍历拆分后的数组,若发现以 %u 开头且长度为 6 的片段,提取后四位十六进制数,使用 pack("H4") 打包成二进制,再通过 iconv("UCS-2","GB2312",...) 转换为目标编码的汉字。
  4. 重组输出:将所有解码后的片段重新连接为完整字符串并返回。
代码如下:
function smarty_modifier_unescape($str)
{
    $str = rawurldecode($str);
    // 匹配 %uXXXX 格式的 Unicode 或普通字符块
    preg_match_all("/(?:%u.{4})|[^%]+/",$str,$r);
    $ar = $r[0];
    foreach($ar as $k=>$v) {
        // 判断是否为 %u 开头的 6 位字符
        if(substr($v,0,2) == "%u" && strlen($v) == 6)
            // 提取最后4位 hex,打包为 UCS-2 字节流并转为 GB2312
            $ar[$k] = iconv("UCS-2","GB2312",@pack("H4",substr($v,-4)));
    }
    return join("",$ar);
}

以上就是 PHP Smarty 自定义函数扩展中关于中文截取、UBB转HTML及Unescape解析的详细内容,更多关于 Smarty 优化技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。