准备工作:创建一个自定义标签示例
为了演示,我们先创建一个简单的自定义标签,假设我们要创建一个标签 {dede:hotartitle/},它的功能是调用指定栏目下最热门的文章标题。

第一步:创建自定义标签文件
-
在
include/tag目录下创建一个新文件,hotartitle.lib.php。 -
在
hotartitle.lib.php中写入以下代码:<?php if(!defined('DEDEINC')) exit('Request Error!'); function lib_hotartitle(&$ctag,&$refObj) { global $dsql; // 1. 获取标签属性 $attlist = "row|10,col|1,typeid|0"; FillAttsDefault($ctag->CAttribute->Items, $attlist); extract($ctag->CAttribute->Items, EXTR_SKIP); // 2. 初始化SQL查询 $innertext = $ctag->GetInnerText(); // 如果没有指定栏目ID,则从当前栏目获取 if(empty($typeid)) { $typeid = GetTopid($refObj->TypeLink->TypeInfos['id']); } $sql = "SELECT arc.id, arc.title, arc.click FROM `dede_archives` arc WHERE arc.typeid = '$typeid' ORDER BY arc.click DESC LIMIT 0, $row"; $dsql->SetQuery($sql); $dsql->Execute(); $artlist = ''; // 3. 循环获取数据并拼接HTML while($row = $dsql->GetArray()) { $artlist .= sprintf($innertext, $row['id'], $row['title'], $row['click']); } return $artlist; } ?>
第二步:创建自定义标签文件

-
在
include/tag目录下创建一个与上面同名的文件,hotartitle.tag.php。 -
在
hotartitle.tag.php中写入以下代码(这个文件是必须的,但内容很简单):<?php if(!defined('DEDEINC')) exit('Request Error!'); require_once(DEDEINC.'/taglib/hotartitle.lib.php'); ?>
你的自定义标签 {dede:hotartitle row='5' typeid='2'} 就可以使用了。
修改列表页模板 (最推荐、最安全)
这是最标准、最安全的方法,因为它不修改任何PHP核心文件,只涉及模板文件。

步骤:
-
打开你的列表页模板文件,通常是
templets/default/list_*.htm( 代表栏目ID)。 -
在模板中直接使用你的自定义标签。
示例 1:在列表页的循环外调用 假设你想在文章列表上方显示一个“热门文章”板块。
<div class="hot-article"> <h3>本站热门文章</h3> <ul> {dede:hotartitle row='5' typeid='2'} <li><a href='[field:id runphp='yes'] $id = @me; $url = GetOneArchive($id); @me = $url['arcurl']; [/field:id]'>[field:title/]</a></li> {/dede:hotartitle} </ul> </div> <!-- 这是Dede默认的文章列表循环 --> {dede:list pagesize='10'} <li> <a href="[field:arcurl/]">[field:title/]</a> <span>[field:pubdate function="MyDate('Y-m-d',@me)"/]</span> </li> {/dede:list}说明:
{dede:hotartitle ...}就是我们创建的自定义标签。typeid='2'指定了要调用栏目ID为2下的热门文章。[field:id ...]这段代码是为了获取文章的URL,因为我们的自定义标签只返回了ID和标题。GetOneArchive()是DedeCMS内置的函数,可以根据ID获取文章的详细信息,包括URL。
示例 2:在列表页的循环内调用 (不推荐,但技术上可行) 如果你想在每个文章列表项后面都加上这个热门文章标签,理论上可以,但这样效率很低,因为会为每篇文章都执行一次SQL查询。
{dede:list pagesize='10'}
<div class="list-item">
<h2><a href="[field:arcurl/]">[field:title/]</a></h2>
<p>发布时间:[field:pubdate function="MyDate('Y-m-d',@me)"]</p>
<!-- 在这里调用自定义标签,但要注意性能 -->
<div class="related-tags">
{dede:hotartitle row='3' typeid='2'}
<span><a href="[field:id runphp='yes'] $id = @me; $url = GetOneArchive($id); @me = $url['arcurl']; [/field:id]">[field:title/]</a></span>
{/dede:hotartitle}
</div>
</div>
{/dede:list}
修改列表页PHP文件 (不推荐,除非必要)
这种方法需要修改 include/arc.listview.class.php 文件,它会把自定义标签编译成PHP代码直接执行,优点是效率最高,缺点是破坏了核心文件,升级DedeCMS时需要重新修改。
步骤:
-
打开PHP文件:
include/arc.listview.class.php。 -
找到
ParseTempletsFirst()函数,这个函数负责解析模板。 -
在函数中添加自定义标签的解析逻辑,通常在处理完
{dede:list}标签之后添加。在
ParseTempletsFirst()函数内,找到类似if($GLOBALS['cfg_list_autopic'])的地方,在其之前或之后添加你的代码。// ... 在 arc.listview.class.php 的 ParseTempletsFirst() 函数中添加 ... // 添加自定义标签 {dede:hotartitle} 的解析 $this->dtp->LoadSource($this->Fields['templet']); if(is_array($this->dtp->CTags)) { foreach($this->dtp->CTags as $tagid=>$ctag) { // 判断是否是我们自定义的标签 if($ctag->GetName() == 'hotartitle') { // 调用我们的自定义标签库函数 $this->dtp->Assign($tagid, lib_hotartitle($ctag, $this)); } } } // ... 继续原有的代码 ... $this->dtp->LoadTemplets(); // ... -
保存文件。
你在列表页模板中使用的 {dede:hotartitle} 标签就会被这个PHP文件直接处理。
警告:
- 升级风险:每次你升级DedeCMS时,这个文件都会被覆盖,你需要手动重新修改。
- 破坏性:直接修改核心类库,不符合“模板与程序分离”的最佳实践。
通过修改PHP核心文件来支持 (最不推荐)
这是最“硬核”的方法,它通过修改DedeCMS的底层代码,让系统“原生”支持你的自定义标签,这种方法极其复杂,且破坏性最大,几乎只在二次开发时使用,普通用户绝对不要尝试。
基本思路:
你需要修改DedeCMS处理标签的底层逻辑,通常是 include/dedetags.class.php 或相关文件,让系统在遇到 {dede:hotartitle} 时,能够像识别 {dede:arclist} 一样去调用 hotartitle.lib.php。
由于这个过程非常复杂,牵涉到DedeCMS的标签引擎,并且极易出错,导致系统崩溃,所以在这里不提供具体代码,如果你有此需求,建议直接寻找有经验的DedeCMS二次开发人员。
总结与最佳实践
| 方法 | 优点 | 缺点 | 推荐度 |
|---|---|---|---|
| 修改列表页模板 | 安全、灵活、升级无忧、符合MVC思想 | 效率相对较低(对于复杂标签) | ★★★★★ (强烈推荐) |
| 修改列表页PHP文件 | 效率最高、直接与逻辑结合 | 破坏核心文件、升级困难、不易维护 | ★★☆☆☆ (除非有特殊性能需求,否则不推荐) |
| 修改PHP核心文件 | 可以实现原生支持 | 极其复杂、风险最高、破坏性最大 | ☆☆☆☆☆ (绝对不推荐给普通用户) |
给你的最终建议:
请务必使用【方法一:修改列表页模板】。 这是DedeCMS官方推荐的最佳实践,也是所有模板引擎的标准做法,它既保证了网站的安全性,又提供了足够的灵活性,足以应对99%的自定义标签调用需求。
