这是一个在模板制作和二次开发中极其常用且重要的函数,主要用于解决中文字符串截断时可能出现的乱码问题。

(图片来源网络,侵删)
cn_substr 是什么?
cn_substr 是织梦CMS内置的一个PHP函数,专门用于截取中文字符串。
它的全称可以理解为 "Chinese Substring"(中文子字符串)。
核心作用: 安全地截取包含中文字符的字符串,确保截断后的字符串不会出现乱码(比如一个汉字被从中间切开)。
为什么需要 cn_substr?
在PHP中,有一个原生的字符串截取函数 substr()。substr() 是按字节来截取的,而不是按字符。

(图片来源网络,侵删)
- 英文字符: 1个字符 = 1个字节。
substr("Hello", 2)返回el,没有问题。 - 中文字符: 在UTF-8编码下,1个中文字符通常占用 3个字节,如果使用
substr("你好世界", 3),它会截取前3个字节,这恰好是“你”这个字的一部分,结果就会是乱码,。
cn_substr 函数就是为了解决这个问题而生的,它能智能地识别UTF-8编码下的中文字符,确保截取时总是以完整的字符为单位。
函数语法与参数
cn_substr 函数通常有两个版本,一个用于PHP代码中,一个在模板中调用。
A. PHP 代码中的用法
cn_substr($string, $length, $start = 0)
参数说明:
$string(string, 必需): 需要被截取的原始字符串。$length(int, 必需): 需要截取的字符数(注意:不是字节数)。$start(int, 可选): 开始截取的位置(从0开始计数),默认为0,即从字符串开头截取。
返回值: 返回截取后的子字符串。

(图片来源网络,侵删)
示例 (PHP):
$title = "这是一个织梦CMS的标题,用于演示cn_substr函数。"; // 截取前10个字符 $short_title = cn_substr($title, 10); echo $short_title; // 输出: 这是一个织梦CMS的 // 注意:'的' 是第10个字符,所以被包含在内。 // 从第5个字符开始,截取5个字符 $another_title = cn_substr($title, 5, 4); echo $another_title; // 输出: 织梦CMS的 // '织'是第4个字符(从0开始是第4位),从它开始数5个。
B. 模板文件中的用法
在织梦的模板文件(.htm)中,你不需要直接调用PHP函数,织梦的模板引擎提供了更简洁的语法,通常通过 function='cn_substr' 来实现。
{dede:field function='cn_substr(@me, $length)'/}
或者更常见的,结合其他字段使用:
{dede:field title function='cn_substr(@me, 40)'/}
模板语法解析:
{dede:field ...}: 这是织梦调用文章字段(如标题、内容摘要等)的标签。: 表示要操作的字段是title)。function='...': 表示要对这个字段的值执行一个PHP函数。@me: 这是织梦模板中的一个特殊变量,代表当前标签的原始值。@me就代表{dede:field.title/}的完整内容。cn_substr(@me, 40): 这部分等同于PHP代码cn_substr($title, 40),表示截取标题的前40个字符。
在模板中的实际应用场景
cn_substr 最常见的应用场景就是文章列表页,用来显示文章标题的摘要或列表标题。
场景1:文章列表页标题截取
假设你的文章标题可能很长,想在列表页只显示前20个字符,后面用省略号(...)代替。
代码示例 (index.htm 或 list_article.htm):
<h3 class="title">
<a href="[field:arcurl/]" title="[field:title/]">
{dede:field.title function='cn_substr(@me, 20)'/}
<!-- 如果想手动添加省略号,可以这样判断 -->
<!--
[field:title runphp='yes']
if(strlen(@me) > 20) @me = cn_substr(@me, 20).'...';
else @me = @me;
[/field:title]
-->
</a>
</h3>
说明:
[field:arcurl/]: 文章的链接地址。[field:title/]: 文章的完整标题(作为a标签的title属性,鼠标悬停时可以看到完整标题)。{dede:field.title function='cn_substr(@me, 20)'/}: 显示截取后的前20个字符作为链接文本。
场景2:文章描述/摘要截取
有时候你需要在列表页显示文章的摘要,但摘要字段 description 可能为空或者内容过长,这时可以截取文章正文 body 的前几个字符作为摘要。
代码示例:
<p class="summary">
{dede:field.description runphp='yes'}
if(empty(@me)) @me = cn_substr(strip_tags(@me), 100); // 如果摘要为空,则截取正文前100字符
else @me = cn_substr(@me, 100); // 如果摘要不为空,则截取摘要前100字符
{/dede:field.description}
</p>
说明:
runphp='yes': 允许在标签内执行PHP代码。strip_tags(@me): 这是一个非常常用的组合,strip_tags函数用于移除字符串中的HTML和PHP标签,防止截断时出现不完整的HTML代码导致页面错乱。cn_substr(...): 在去除标签后,再进行安全的中文截取。
总结与注意事项
| 特性/函数 | substr() (PHP原生) |
cn_substr() (织梦) |
|---|---|---|
| 编码安全 | 不安全,UTF-8下中文易乱码 | 安全,专为UTF-8中文设计 |
| 截取单位 | 字节 | 字符 |
| 主要用途 | 英文或字节精确控制 | 的截取 |
| 模板调用 | 不可直接调用 | {dede:field function='cn_substr(...)'} |
| 常用组合 | - | strip_tags() + cn_substr() |
核心要点:
- 首选中文截取: 只要在织梦模板中处理任何可能包含中文的文本(标题、描述等),并且需要截断,就应该优先使用
cn_substr。 @me的含义: 在模板的function属性中,@me永远代表当前标签的原始值,理解这一点是正确使用模板函数的关键。- 与
mb_substr的关系:cn_substr的底层实现通常依赖于mb_substr(Multi-Byte String Substring) 函数,并确保在织梦的UTF-8环境下正确配置了字符集,对于不熟悉多字节函数的开发者来说,cn_substr是一个更简单、更安全的封装。
希望这份详细的解释能帮助你完全掌握织梦CMS中的 cn_substr 函数!
