核心思路
- 创建自定义表单:在后台创建一个用于收集数据的自定义表单。
- 获取表单ID:记录下这个表单的唯一ID。
- 修改列表模板:在
list_*.htm模板文件中,使用{dede:list}或{dedarclist}标签是不行的,因为这些标签只用于dede_archives表,我们需要使用{dede:sql}标签来直接执行数据库查询。 - 编写SQL查询:编写一个 SQL 语句,从自定义表单的数据表中查询数据,并关联
dede_arctype表来获取栏目名称等信息。 - 集成分页:将查询到的总记录数等信息传递给 DedeCMS 的分页函数
GetPageList(),生成正确的分页链接。
详细步骤
第一步:创建自定义表单并获取数据表名
- 登录 DedeCMS 后台。
- 进入「核心」 -> 「内容发布管理」 -> 「自定义表单」。
- 点击「新增自定义表单」,我们创建一个名为“用户反馈”的表单。
- 在表单中添加一些字段,
title(文本,标题)name(文本,姓名)content(多行文本,反馈内容)addtime(时间,提交时间)
- 保存表单,DedeCMS 会自动创建一个数据表来存储这些信息,表名通常是
dede_addonXX,XX是一个数字,你可以在「自定义表单」列表中看到你创建的表单,鼠标悬停在上面,浏览器状态栏会显示链接,里面就包含了tablename=dede_addonXX,或者你也可以直接在数据库的dede_addon表中查找确认。假设我们得到的数据表名是dede_addon18。
第二步:找到并修改列表模板文件
假设你要在“网站首页”或某个栏目页的列表中显示这些反馈,你需要找到对应的模板文件。

- 如果是首页,通常是
index.htm。 - 如果是栏目列表页,ID 为 1 的栏目,模板文件是
list_1.htm。
我们以修改栏目列表页 list_1.htm 为例。
第三步:编写模板代码(关键步骤)
打开 list_1.htm 文件,将原来的 {dede:list} 标签替换为以下代码。
重要提示:请将代码中的 18 替换为你自己创建的自定义表单对应的 addon ID(即数据表名中的数字)。
{dede:sql sql="
SELECT
a.id,
a.title,
a.name,
a.content,
a.arctypedir,
a.addtime,
t.typename,
t.channeltype
FROM
`#@__addon18` a
LEFT JOIN
`#@__arctype` t ON a.typeid = t.id
ORDER BY
a.id DESC
"}
<li>
<strong>标题:</strong>[field:title/]
<span>提交人:[field:name/]</span>
<span>时间:[field:pubdate function="MyDate('Y-m-d H:i',@me)"/]</span>
<p>内容:[field:content function="htmlspecialchars_decode(@me)"/]</p>
<p>所属栏目:<a href="[field:typedir/]/">[field:typename/]</a></p>
</li>
{/dede:sql}
代码解释:

{dede:sql}:这是 DedeCMS 的原生 SQL 查询标签。SELECT ...:这是 SQL 查询语句。#@__addon18:#@__是 DedeCMS 的数据库表前缀(通常是dede_),addon18就是我们第一步找到的数据表名。a:是给#@__addon18表起的别名,方便引用。LEFT JOIN ...:因为我们想显示栏目名称,所以需要关联#@__arctype表(栏目表)。ORDER BY a.id DESC:按表单提交的ID降序排列,即最新的在最前面。
[field:字段名/]:这是用来显示查询结果的字段,这里的字段名是 SQL 语句SELECT后面指定的别名(如a.title,t.typename)。function="...":对字段值进行函数处理。MyDate('Y-m-d H:i',@me):将 Unix 时间戳格式化为更易读的日期时间。htmlspecialchars_decode(@me):因为提交表单时,内容可能会被转义(<变成<),这里将其反转义回来,显示为正常的 HTML。
第四步:实现分页(最核心、最容易出错的地方)
分页不能直接在 {dede:sql} 标签内完成,我们需要手动计算总记录数,然后调用 DedeCMS 的分页函数。
-
在模板文件顶部引入分页函数: 在
list_1.htm的最顶部,在{dede:include filename="head.htm"/}之前,加入以下代码:{dede:sql sql="SELECT COUNT(*) as total FROM `#@__addon18`"} {dede:global.total/} {/dede:sql}这一小段代码的作用是查询出
addon18表的总记录数,并通过{dede:global.total/}将这个数字传递给整个模板环境,DedeCMS 的分页函数会自动获取这个全局变量。 -
在列表循环后添加分页代码: 在
{dede:sql}循环结束之后,{dede:include filename="foot.htm"/}之前,添加分页代码:
(图片来源网络,侵删)<div class="dede_pages"> <ul> {dede:pagelist listsize="4" listitem="info,index,end,pre,next,pageno"} {/dede:pagelist} </ul> </div> -
修改
arc.listview.class.php文件(非常重要): 这是实现分页的关键步骤,因为 DedeCMS 的分页函数默认是为文章列表设计的,我们需要让它“知道”我们查询的是自定义表单的总记录数。- 文件路径:
/include/arc.listview.class.php - 找到函数:打开这个文件,找到
GetPageListDM函数(大约在第 600 行左右,不同版本行号可能略有差异)。 - 修改代码:在函数内找到
$this->TotalResult这个赋值语句,默认情况下,它是通过查询dede_archives表来获取的,我们需要修改它,让它使用我们之前通过{dede:global.total/}传递过来的值。
找到类似这样的代码:
// ... 在 GetPageListDM 函数内 ... if(empty($this->TotalResult)) { $this->TotalResult = $this->dsql->GetOne("Select count(*) as dd From `dede_archives` where arcrank > -1 $cquery "); $this->TotalResult = $this->TotalResult['dd']; } // ...将其修改为:
// ... 在 GetPageListDM 函数内 ... // 优先使用通过模板传递过来的总记录数 if (isset($GLOBALS['totalresult']) && is_numeric($GLOBALS['totalresult'])) { $this->TotalResult = $GLOBALS['totalresult']; } else { // 如果没有传递,则回退到原来的默认查询方式(查询文章表) if(empty($this->TotalResult)) { $this->TotalResult = $this->dsql->GetOne("Select count(*) as dd From `dede_archives` where arcrank > -1 $cquery "); $this->TotalResult = $this->TotalResult['dd']; } } // ...修改逻辑说明:我们增加了对
$GLOBALS['totalresult']的判断,如果这个全局变量存在且是数字,我们就直接使用它作为总记录数,这样,分页逻辑就和我们自定义的 SQL 查询关联起来了。 - 文件路径:
-
在列表模板中设置每页显示数量: 在
{dede:sql}标签上,需要指定pagesize属性,即每页显示多少条。{dede:sql sql="..." pagesize="10"} <!-- 循环内容 --> {/dede:sql}
完整的 list_1.htm 示例
{dede:include filename="head.htm"/}
<!-- 第1步:获取总记录数,供分页使用 -->
{dede:sql sql="SELECT COUNT(*) as total FROM `#@__addon18`"}
{dede:global.total/}
{/dede:sql}
<h1>用户反馈列表</h1>
<!-- 第2步:使用sql标签循环输出数据,并设置每页显示10条 -->
{dede:sql sql="
SELECT
a.id,
a.title,
a.name,
a.content,
a.addtime,
t.typename,
t.typedir
FROM
`#@__addon18` a
LEFT JOIN
`#@__arctype` t ON a.typeid = t.id
ORDER BY
a.id DESC
" pagesize="10"}
<li>
<strong>标题:</strong>[field:title/]
<span>提交人:[field:name/]</span>
<span>时间:[field:pubdate function="MyDate('Y-m-d H:i',@me)"/]</span>
<p>内容:[field:content function="htmlspecialchars_decode(@me)"/]</p>
<p>所属栏目:<a href="[field:typedir/]/">[field:typename/]</a></p>
</li>
{/dede:sql}
<!-- 第3步:添加分页链接 -->
<div class="dede_pages">
<ul>
{dede:pagelist listsize="4" listitem="info,index,end,pre,next,pageno"}
{/dede:pagelist}
</ul>
</div>
{dede:include filename="foot.htm"/}
总结与注意事项
- 数据表名:
#@__addonXX中的XX一定要替换成你自己的。 - SQL 语句:根据你的实际表结构调整
SELECT的字段和FROM/JOIN的表。 - 分页核心:修改
arc.listview.class.php文件是分页能否成功的决定性步骤,请务必谨慎操作,修改前最好备份原文件。 - 权限:确保运行网站的用户对
#@__addon18表有查询权限。 - 性能:如果自定义表单数据量非常大(上万条),直接
SELECT *并分页可能会对数据库造成压力,可以考虑为id字段添加索引,或者在 SQL 语句中使用LIMIT进行更高效的分页(但这会与 DedeCMS 的分页函数耦合,不如上述方法通用)。
按照以上步骤操作,你就可以成功地在 DedeCMS 列表页调用自定义表单数据并实现分页了。
