先调用当前栏目的所有子栏目,然后获取这些子栏目下的所有文章,最后对这批文章进行分页。

(图片来源网络,侵删)
下面我将提供两种最主流和推荐的方法,并附上详细的代码解释。
场景说明
假设我们有一个栏目结构如下:
- 网站首页
- 产品中心 (ID=1)
- 子栏目A (ID=2)
- 子栏目B (ID=3)
- 子栏目C (ID=4)
当你访问“产品中心”的列表页(list.php?tid=1)时,我们希望页面能同时显示子栏目A、B、C下的所有文章,并进行分页。
使用 arclist 标签(推荐,更灵活)
这是最常用且最灵活的方法,它通过 arclist 标签的 typeid 和 subday 等属性来获取文章,然后通过 pagelist 标签实现分页。

(图片来源网络,侵删)
准备工作:修改列表页模板
打开你的列表页模板文件,通常位于 /templets/default/list_*.htm( 是栏目ID,或者直接是 /templets/default/list.htm 作为通用模板)。
在模板中添加代码
在需要显示子栏目文章列表和分页的地方,放入以下代码:
{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}
<!-- 分页代码 -->
<div class="dede_pages">
<ul class="pagelist">
{dede:pagelist listitem="info,index,end,pre,next,pageno" listsize="5"/}
</ul>
</div>
关键点:
{dede:list}: 这个标签本身就是一个循环,用于获取文章列表。默认情况下,它只会获取当前栏目($typeid)下的文章。pagesize='10': 设置每页显示10篇文章。{dede:pagelist}: 这个标签负责生成分页链接。它会自动识别{dede:list}所生成的数据,并进行分页。
核心步骤:修改 include/arc.listview.class.php 文件
这是实现“调用子栏目文章”的关键一步,我们需要修改 DedeCMS 的核心类文件,让它能识别我们传递过来的特殊参数。

(图片来源网络,侵删)
-
备份文件:在修改
/include/arc.listview.class.php之前,务必备份原文件! -
找到并修改代码:
- 用代码编辑器打开
/include/arc.listview.class.php。 - 按快捷键
Ctrl + F搜索function GetArcList,找到这个函数。 - 在这个函数内,找到
if($this->TypeLink->TypeInfos['reid'] == 0)这段代码(通常在第200行左右)。 - 在
if($this->TypeLink->TypeInfos['reid'] == 0)的代码块内部,找到类似$this->dsql->SetQuery("SELECT id,typename,typedir,isdefault,isdefaultpic,namerule2,moresite,siteurl,sitepath FROMdede_arctypeWHERE reid='".$this->TypeID."' AND ishidden<>1 order by sortrank asc");的SQL查询语句。 - 将这段SQL查询语句修改为以下代码:
// 修改前 // $this->dsql->SetQuery("SELECT id,typename,typedir,isdefault,isdefaultpic,namerule2,moresite,siteurl,sitepath FROM `dede_arctype` WHERE reid='".$this->TypeID."' AND ishidden<>1 order by sortrank asc"); // 修改后 // 获取当前栏目ID $currentTypeId = $this->TypeID; // 查询所有子栏目的ID $sontypeids = ''; $dsql_son = new DedeSql(false); $dsql_son->SetQuery("SELECT id FROM `dede_arctype` WHERE reid='$currentTypeId' AND ishidden<>1 order by sortrank asc"); $dsql_son->Execute('a'); while ($row_son = $dsql_son->GetArray('a')) { $sontypeids .= ($sontypeids == '' ? $row_son['id'] : ','.$row_son['id']); } $dsql_son->Close(); // 如果存在子栏目,则typeid参数变为 "子栏目ID,当前栏目ID" if($sontypeids != ''){ $this->TypeID = $sontypeids . ',' . $currentTypeId; } - 用代码编辑器打开
代码解释:
- 这段代码的作用是:当系统准备获取文章列表时,它会检查当前栏目是否有子栏目。
- 如果有,它会获取所有子栏目的ID,并组合成一个ID字符串("2,3,4,1")。
- 它把这个ID字符串重新赋值给
$this->TypeID。 - 这样,
{dede:list}标签在执行时,typeid参数就变成了所有子栏目ID加上当前栏目ID,从而实现了调用子栏目文章的功能。
完成
保存并上传修改后的 arc.listview.class.php 文件,访问你的列表页,就能看到所有子栏目的文章,并且分页功能也正常工作了。
使用 sql 标签(更直接,性能略优)
如果你对SQL比较熟悉,或者觉得方法一修改核心文件有些麻烦,可以使用 sql 标签直接查询数据库,然后手动分页。
在列表页模板中添加代码
<!-- 使用sql标签获取文章 -->
{dede:sql sql='
SELECT
a.id, a.title, a.typeid, a.pubdate, a.litpic, t.typename, t.typedir
FROM
dede_archives AS a
LEFT JOIN
dede_arctype AS t ON a.typeid = t.id
WHERE
a.typeid IN ([!--获取当前栏目ID--])
ORDER BY
a.pubdate DESC
'}
<li>
<a href="[field:typedir function='MakeOneDir(@me)'/]/[field:id/].html">[field:title/]</a>
<span>[field:pubdate function="MyDate('Y-m-d',@me)"/]</span>
</li>
{/dede:sql}
<!-- 手动分页代码(此方法分页较复杂,通常不推荐) -->
<!-- 更推荐使用方法一 -->
这个方法的缺点:
- 分页复杂:
{dede:sql}标签本身不自带分页功能,你需要手动编写分页逻辑,非常麻烦,容易出错。 - 性能问题:如果子栏目很多,文章量很大,直接查询
dede_archives表可能不如 DedeCMS 内置的优化机制高效。
除非有特殊需求,否则强烈推荐使用方法一。
总结与对比
| 特性 | 方法一 (arclist + 修改核心文件) |
方法二 (sql
|
|---|---|---|
| 易用性 | 高,修改一次文件后,模板里只需写简单的标签。 | 低,需要手写SQL,分页逻辑复杂。 |
| 灵活性 | 高,可以结合所有 arclist 和 list 的标签属性。 |
中,可以自定义SQL,但受限于标签功能。 |
| 性能 | 好,利用了DedeCMS的缓存和查询优化机制。 | 一般,直接查询大表,可能不如内置优化。 |
| 维护性 | 低,修改了核心文件,升级DedeCMS时可能需要重新修改。 | 高,不修改核心文件,升级无忧。 |
| 推荐度 | ⭐⭐⭐⭐⭐ (强烈推荐) | ⭐⭐ (仅适用于特殊场景) |
最终建议:
对于绝大多数用户,请选择 方法一,它虽然需要修改一个核心文件,但带来的便利性和稳定性是值得的,请务必在修改前备份文件,并在升级系统后注意检查是否需要重新应用此修改。
